<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:base="https://johnvidler.co.uk/">
  <title>JohnVidler.co.uk</title>
  <subtitle>The ramblings of Dr John Vidler on Code, Tech, Maker stuff, and Fatherhood</subtitle>
  <link href="https://johnvidler.co.uk/feed.xml" rel="self" />
  <link href="https://johnvidler.co.uk/" />
  
  <updated>2025-11-26T00:00:00Z</updated>
  <id>https://johnvidler.co.uk/</id>
  <author>
    <name>John Vidler</name>
    <email>website@johnvidler.co.uk</email>
  </author>
  <entry>
    <title>Text-Only Copyable Shopping Baskets</title>
    <link href="https://johnvidler.co.uk/blog/text-only-copyable-shopping-baskets/" />
    <updated>2025-11-26T00:00:00Z</updated>
    <id>https://johnvidler.co.uk/blog/text-only-copyable-shopping-baskets/</id>
    <content
      xml:lang=""
      type="html"
      >&lt;p&gt;I’ve been ordering a large number of things from &lt;a href=&quot;https://thepihut.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ThePiHut&lt;/a&gt; lately, and the university procurement system needs quite a few details of each order line so they can actually make the purchase.&lt;/p&gt;
&lt;p&gt;Unfortunately, ThePiHut’s website does not include an ‘export basket’ or other equivalent mechanism that I can use to send all these details to our procurement folks… so in the usual fasion of a developer faced with a code-based problem, I wrote a code-based solution.&lt;/p&gt;
&lt;p&gt;I wrote a &lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/greasemonkey/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;GreaseMonkey&lt;/a&gt; / &lt;a href=&quot;https://www.tampermonkey.net/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;TamperMonkey&lt;/a&gt; script that only runs on the basket page of ThePiHut, and pulls all the details of each item in your basket, dropping them all into a single text box with all the information a procurement department could want.&lt;/p&gt;
&lt;p&gt;This simple script I’ve &lt;a href=&quot;https://gist.github.com/JohnVidler/e57b0009391e8582ae5cf2431372d85a&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;posted on Github as a Gist&lt;/a&gt;, which both systems can use as an install and update source (although I do consider this ‘complete’ so probably won’t change it much now). Or you can copy the frozen copy of this gist from the code box below this post.&lt;/p&gt;
&lt;p&gt;Hopefully this won’t be needed forever as the folks at ThePiHut could easily add identical functionality into the website itself, but for now, it saves me a ton of time, and it might save you some too.&lt;/p&gt;
&lt;pre class=&quot;language-plaintext&quot;&gt;&lt;code class=&quot;language-plaintext&quot;&gt;// ==UserScript==
// @name         ThePiHut Text Basket
// @namespace    https://johnvidler.co.uk/
// @website      https://johnvidler.co.uk/
// @source       https://gist.github.com/JohnVidler/e57b0009391e8582ae5cf2431372d85a
// @version      2025-11-26
// @description  Creates a simple copy/pasteable shopping cart to send to procurement departments for ThePiHut.com
// @author       John Vidler
// @match        https://thepihut.com/cart
// @icon         https://www.google.com/s2/favicons?sz=64&amp;amp;domain=thepihut.com
// @grant        none
// @require      https://code.jquery.com/jquery-3.7.1.min.js
// ==/UserScript==

// USAGE: Install Tampermonkey or Greasemonkey into your browser, create a new script and drop this file&#39;s contents into it. That&#39;s it!
//        When you next visit the basket page on ThePiHut you&#39;ll have an extra box under the cart total with a text-only copy of the current cart.

(function () {
    &#39;use strict&#39;;

    let _copyableBOM = &quot;&quot;;

    function copyToClipboard(){
        navigator.clipboard.writeText(_copyableBOM);
        alert( &quot;Copied basket to clipboard&quot; );
    }

    function addButton(text, onclick, cssObj) {
        cssObj = cssObj || {position: &#39;absolute&#39;, bottom: &#39;7%&#39;, left:&#39;4%&#39;, &#39;z-index&#39;: 3}
        let button = document.createElement(&#39;button&#39;), btnStyle = button.style
        document.body.appendChild(button)
        button.innerHTML = text
        button.onclick = onclick
        Object.keys(cssObj).forEach(key =&gt; btnStyle[key] = cssObj[key])
        return button
    }

    function buildBOM(){
        const $ = window.jQuery;
        console.log(&quot;jQuery version:&quot;, $.fn.jquery);

        const lines = $(&#39;.line-item&#39;);

        const parts = [];
        let total = 0;
        for( var i=0; i&amp;lt;lines.length; i++ ) {
            const line = lines.get(i);
            const fPrice = parseFloat($(line).find(&#39;span.price--convertible&#39;).attr(&#39;data-base-amount&#39;));
            parts.push({
                vendor: $(line).find(&#39;a.line-item-meta__vendor&#39;).text(),
                title: $(line).find(&#39;a.line-item-meta__title&#39;).text(),
                quantity: $(line).find(&#39;input.quantity-selector__input&#39;).val(),
                link: &quot;https://thepihut.com&quot; + $(line).find(&#39;a.line-item-meta__title&#39;).attr(&quot;href&quot;),
                price: fPrice
            });

            total += fPrice;
        }

        let formattedOutput = parts.map( v =&gt; [
            `(${v.quantity}x) ${v.title}`,
            `&#92;t - ${v.link}`,
            `&#92;t - Vendor: ${v.vendor}`,
            `&#92;t - £${v.price.toFixed(2)} Total (£${(v.price/v.quantity).toFixed(2)} each)`,
        ].join(&#39;&#92;n&#39;) ).join(&quot;&#92;n&#92;n&quot;);

        formattedOutput += `&#92;n&#92;nTotal without shipping: £${total.toFixed(2)}&#92;n`

        _copyableBOM = formattedOutput;

        const newHTML = [
            `&amp;lt;div class=&quot;cart-upsells&quot; style=&#39;margin-top: 3rem;&#39;&gt;`,
            `&amp;lt;div class=&quot;o-container&quot;&gt;`,
            `&amp;lt;h3 style=&#39;text-align:center;&#39;&gt;&amp;lt;strong&gt;Text-Only Basket&amp;lt;/strong&gt;&amp;lt;/h3&gt;`,
            &quot;&amp;lt;p&gt;Copy &amp;amp;amp; Paste this to send to your procurement department, notes document, or anywhere else you might need a text-only copy of this basket.&amp;lt;/p&gt;&quot;,
            `&amp;lt;p&gt;&amp;lt;textarea style=&#39;width:100%; height:20rem; resize:none;&#39; wrap=false&gt;${formattedOutput}&amp;lt;/textarea&gt;&amp;lt;/p&gt;`,
            &quot;&amp;lt;p style=&#39;text-align: center; color: gray;&#39;&gt;A tiny utility by &amp;lt;a href=&#39;https://johnvidler.co.uk/&#39; target=&#39;_blank&#39;&gt;John Vidler&amp;lt;/a&gt;. No association with ThePiHut implied&amp;lt;/p&gt;&quot;,
            `&amp;lt;/div&gt;`,
            `&amp;lt;/div&gt;`
        ];

        //$(&#39;div.cart__content&#39;).append( newHTML.join(&#39;&#39;) );
        $(&#39;safe-sticky.cart__aside-inner&#39;).append( newHTML.join(&#39;&#39;) );
    }

    // Delay slightly to allow for any lazy loading and/or net delays
    setTimeout( () =&gt; buildBOM(), 100 );
})();&lt;/code&gt;&lt;/pre&gt;
</content
    >
  </entry>
  <entry>
    <title>KiCAD Footprints with Multiple Parts for PCBA</title>
    <link href="https://johnvidler.co.uk/blog/kicad-footprints-with-multiple-parts-for-pcba/" />
    <updated>2025-10-10T00:00:00Z</updated>
    <id>https://johnvidler.co.uk/blog/kicad-footprints-with-multiple-parts-for-pcba/</id>
    <content
      xml:lang=""
      type="html"
      >&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/kicad/2part-original-symbol.png&quot; class=&quot;small&quot; /&gt;
    &lt;figcaption&gt;The original symbol as defined in the official mikroBUS library&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The process begins with an original component that consists of two physically independent connectors housed in a single package. This is a common scenario with certain types of board-to-board connectors or specialized interface headers where manufacturing constraints require separate physical components, but the electrical design treats them as a unified part.&lt;/p&gt;
&lt;p&gt;To start the modification process, open the symbol in KiCAD’s symbol editor. Create two duplicate copies of this original symbol - one designated as the ‘left’ variant and another as the ‘right’ variant. The terms ‘left’ and ‘right’ here should be adjusted to match the actual geometry of your specific part, or whatever logical separation makes sense for your design. The key is establishing a clear distinction between the two physical components.&lt;/p&gt;
&lt;figure&gt;
    &lt;figure&gt;
        &lt;img src=&quot;https://johnvidler.co.uk/assets/images/kicad/2part-left-symbol.png&quot; class=&quot;small&quot; /&gt;
        &lt;figcaption&gt;The new left-hand symbol&lt;/figcaption&gt;
    &lt;/figure&gt;
    &lt;figure&gt;
        &lt;img src=&quot;https://johnvidler.co.uk/assets/images/kicad/2part-right-symbol.png&quot; class=&quot;small&quot; /&gt;
        &lt;figcaption&gt;The new right-hand symbol&lt;/figcaption&gt;
    &lt;/figure&gt;
&lt;/figure&gt;
&lt;p&gt;Once you have your duplicated symbols, begin editing the left variant by carefully deleting all the connector pins that correspond to the right physical connector. This is where attention to detail becomes critical: you must preserve the original pin numbers during this deletion process. The pin numbering must remain consistent with the original part datasheet, as this maintains the electrical connections when you eventually place both parts on your PCB. Repeat this process in reverse for the right symbol variant, removing all the left connector pins while again preserving the pin numbers.&lt;/p&gt;
&lt;p&gt;With the symbols prepared, transition to KiCAD’s footprint editor and locate the corresponding footprint for your part. In my case, I started with a standard through-hole variant, but found it necessary to create a custom surface-mount variant using offset pin headers to meet the assembly requirements. The specific mounting style you choose will depend on your manufacturing process and board design constraints.&lt;/p&gt;
&lt;figure&gt;
    &lt;figure&gt;
        &lt;img src=&quot;https://johnvidler.co.uk/assets/images/kicad/2part-mikrobus-footprint-orig.png&quot; class=&quot;small&quot; /&gt;
        &lt;figcaption&gt;The original library-supplied footprint&lt;/figcaption&gt;
    &lt;/figure&gt;
    &lt;figure&gt;
        &lt;img src=&quot;https://johnvidler.co.uk/assets/images/kicad/2part-smt-variant.png&quot; class=&quot;small&quot; /&gt;
        &lt;figcaption&gt;My modified SMT footprint&lt;/figcaption&gt;
    &lt;/figure&gt;
&lt;/figure&gt;
&lt;p&gt;The next crucial step involves establishing a clear division line on the footprint. Draw a ‘cut’ line that defines where the part will be split - I recommend using the &lt;code&gt;F.fab&lt;/code&gt; layer for this purpose, as it’s intended for fabrication documentation. Critically, ensure this cut line is aligned to the editor grid, as this alignment will make reassembly in the PCB layout much cleaner and prevent any potential alignment issues during placement.&lt;/p&gt;
&lt;p&gt;Following the same pattern used with the symbols, duplicate the footprint twice to create left and right variants corresponding to each physical component. On the left footprint, methodically remove all elements on the right side of your cut line - this includes pads, mounting holes, silkscreen markings, and any other footprint features. Then perform the inverse operation on the right footprint, removing all left-side elements. The result should be two footprints that, when placed together, perfectly reconstruct the original part geometry.&lt;/p&gt;
&lt;figure&gt;
    &lt;figure&gt;
        &lt;img src=&quot;https://johnvidler.co.uk/assets/images/kicad/2part-smt-variant-left.png&quot; class=&quot;small&quot; /&gt;
    &lt;/figure&gt;
    &lt;figure&gt;
        &lt;img src=&quot;https://johnvidler.co.uk/assets/images/kicad/2part-smt-variant-right.png&quot; class=&quot;small&quot; /&gt;
    &lt;/figure&gt;
    &lt;figcaption&gt;The two halves of the footprint, note that both have a common centerline aligned to the grid.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Return to your PCB layout editor where the payoff becomes apparent. Place both the left and right footprint variants on your board, carefully aligning them along the cut line you established earlier. When properly aligned, they should seamlessly rebuild the complete part as if it were never split. This alignment is why the grid-snapping during the cut line creation was so important.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/kicad/2part-3d-render-final.png&quot; class=&quot;small&quot; /&gt;
    &lt;figcaption&gt;The final configuration in the board render from KiCAD&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The final benefit of this approach shows in your Bill of Materials. Instead of a single entry for the composite part, you now have two BOM entries. This separation allows you to specify two distinct physical parts for placement, which is exactly what PCBA (Printed Circuit Board Assembly) services require. This resolves the fundamental 1:1 part mapping issue where assembly systems expect each footprint to correspond to exactly one physical component, avoiding the confusion and potential errors that arise when a single BOM entry needs to map to multiple placement locations.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/kicad/2part-bom-entries.png&quot; /&gt;
    &lt;figcaption&gt;The generated BOM (in the JLCPCB plugin) showing two PCBA parts&lt;/figcaption&gt;
&lt;/figure&gt;</content
    >
  </entry>
  <entry>
    <title>3D Printable Accessibility Switches</title>
    <link href="https://johnvidler.co.uk/blog/3d-printable-accessibility-switches/" />
    <updated>2024-05-30T00:00:00Z</updated>
    <id>https://johnvidler.co.uk/blog/3d-printable-accessibility-switches/</id>
    <content
      xml:lang=""
      type="html"
      >&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/hardware/access-bit/low-cost-paddle-switches.png&quot; /&gt;
    &lt;figcaption&gt;Two basic paddle switches fully assembled. My 3d printer needs some attention, so some of the detail is lost, but they function just fine.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Based around a low-profile keyboard keyswitch this was pretty much the simplest, lowest-profile paddle I could construct in time for the conference, so they’re a bit rough around the edges (especially on the lettering, and stringing on the curved surfaces) as I had little time to fine tune the design or deal with recalibrating my slightly aging 3D printer.&lt;br /&gt;
The filament I used was also ‘whatever was loaded into the printer’, so you get what you get. I fully suspect a better 3D printer, or better filament, or just using a 3D printing service would yield far better results.&lt;/p&gt;
&lt;h3 id=&quot;assembly-details&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/3d-printable-accessibility-switches/#assembly-details&quot;&gt;Assembly Details&lt;/a&gt;&lt;/h3&gt;
&lt;h4 id=&quot;step-0-parts-and-soldering&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/3d-printable-accessibility-switches/#step-0-parts-and-soldering&quot;&gt;Step 0 - Parts and Soldering&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Print the parts as many times as you need for however many switches you require.&lt;/p&gt;
&lt;ul class=&quot;list&quot;&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://johnvidler.co.uk/assets/3d/able-paddle/v5/Base.stl&quot;&gt;Base (.stl)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://johnvidler.co.uk/assets/3d/able-paddle/v5/Paddle.stl&quot;&gt;Paddle with ‘PRESS’ text (.stl)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://johnvidler.co.uk/assets/3d/able-paddle/v5/Paddle-no-text.stl&quot;&gt;Paddle with no text (.stl)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://johnvidler.co.uk/assets/3d/able-paddle/v5/0.2mm_PLA_MK3S_1h18m.gcode&quot;&gt;GCode (for Prusa mk3) - includes one of each part&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://johnvidler.co.uk/assets/3d/able-paddle/v5/2x_notext_0.2mm_PLA_MK3S_1h18m.gcode&quot;&gt;GCode (for Prusa mk3) - includes 2 of each part&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://johnvidler.co.uk/assets/3d/able-paddle/v5/4x_notext_0.2mm_PLA_MK3S_1h18m.gcode&quot;&gt;GCode (for Prusa mk3) - includes 4 of each part&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.amazon.co.uk/gp/product/B07TSZQ8XL&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;3.5mm Stereo Jack Panel Mount Connector&lt;/a&gt; - Or equivalent&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://thepihut.com/products/kailh-choc-low-profile-red-linear-key-switches-10-pack&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Kailh CHOC Low Profile Red Linear Key Switches&lt;/a&gt; - Or equivalent&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The wiring is trivial, but may require some trial-and-error if your equipment differs from mine. In my case the tip and sleeve of the 3.5mm jack are the critical pins, and bridging them with the switch is what I need, but if you have other connections, I suggest getting ahold of the TRRS sockets, connecting them up in isolation then bridging pairs of contacts until you find the pair that work for you. In my case, the pins I needed were pins 2 and 4.&lt;/p&gt;
&lt;p&gt;When soldering the switch and jack, keep in mind that you may not want much slack in the wires between the two, as this may interfere with the switch operation. To ensure I had the correct length, I used the base of the switch as both a template and a holder while soldering.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/hardware/access-bit/a0-paddle-assembly.png&quot; /&gt;
    &lt;figcaption&gt;The soldered keyboard switch, and both halves of the paddle switch. The holes in the base are for hard-mounting to other equipment with screws.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h4 id=&quot;step-1-attaching-the-trrs-socket&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/3d-printable-accessibility-switches/#step-1-attaching-the-trrs-socket&quot;&gt;Step 1 - Attaching the TRRS Socket&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Unscrew the nut on the TRRS socket almost all the way off, then snap the socket into the back of the paddle base. The ring on the socket should fit neatly into the slot and hold it with a satisfying click.&lt;/p&gt;
&lt;p&gt;Optionally screw the nut back down onto the socket to secure it, although in my testing no nut is actually needed, but I kept mine on for the aesthetics.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/hardware/access-bit/a1-paddle-assembly.png&quot; /&gt;
    &lt;figcaption&gt;Snapping the TRRS socket into the 3D printed base. It really is very satisfying how well this works!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h4 id=&quot;step-2-attaching-the-keyboard-switch&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/3d-printable-accessibility-switches/#step-2-attaching-the-keyboard-switch&quot;&gt;Step 2 - Attaching the Keyboard Switch&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Slot the keyboard switch into the square mounting; it should fit &lt;em&gt;just so&lt;/em&gt; such that the bottom half of the switch neatly slides into the mounting, but the upper section is held at the correct height.&lt;/p&gt;
&lt;p&gt;When you do this, ensure that the two wires from the switch are routed around to the cutout without pinching them. They should fit neatly under the body of the switch.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/hardware/access-bit/a2-paddle-assembly.png&quot; /&gt;
    &lt;figcaption&gt;Mounting the switch. In theory this should work for deeper &#39;Cherry&#39; style keyboard switches as well, but the cases may be too deep to fit in the current mounting, or the switch stem may be too long to neatly close. The low-profiles ones give a nice flat profile.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h4 id=&quot;step-3-attaching-the-paddle&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/3d-printable-accessibility-switches/#step-3-attaching-the-paddle&quot;&gt;Step 3 - Attaching the Paddle&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Take a length of printer filament (1.75mm diameter) and slide it into one of the holes in the hinges, then line the lid up with the protruding filament and push it all the way through the far hinge mounting.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/hardware/access-bit/a3-paddle-assembly.png&quot; /&gt;
    &lt;figcaption&gt;Feeding the hinge filament through. This can be a little fiddly depending on the dimensional accuracy of your printer.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;If you encounter resistance, try spinning the filament around to align better - I found that letting the natural curve of the filament go upwards was the best way, as it tended to guide through the center open section of the hinge.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/hardware/access-bit/a4-paddle-assembly.png&quot; /&gt;
    &lt;figcaption&gt;The attached paddle with some spare filament.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h4 id=&quot;step-5-trim-and-use!&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/3d-printable-accessibility-switches/#step-5-trim-and-use!&quot;&gt;Step 5 - Trim and Use!&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Cut off any excess filament with some edge-cutters, optionally adding a dot of glue to one or both ends of the hinge to secure it, although I personally found that the curve of the filament and the minimal actual rotation when using the paddle meant that this was not required.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/hardware/access-bit/a5-paddle-assembly.png&quot; /&gt;
    &lt;figcaption&gt;A completed paddle switch, ready for use!&lt;/figcaption&gt;
&lt;/figure&gt;</content
    >
  </entry>
  <entry>
    <title>The Access:bit - An Accessibility Addon for the Micro:bit</title>
    <link href="https://johnvidler.co.uk/blog/the-accessbit-an-accessibility-addon-for-the-microbit/" />
    <updated>2024-05-27T00:00:00Z</updated>
    <id>https://johnvidler.co.uk/blog/the-accessbit-an-accessibility-addon-for-the-microbit/</id>
    <content
      xml:lang=""
      type="html"
      >&lt;p&gt;For the past two years I have worked with the &lt;a href=&quot;https://microbit.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Micro:bit Educational Foundation&lt;/a&gt; and in that time I’ve developed &lt;a href=&quot;https://johnvidler.co.uk/blog/the-microbit-gps-logger-prototype&quot;&gt;several&lt;/a&gt; &lt;a href=&quot;https://johnvidler.co.uk/blog/the-clipbit-an-addon-for-the-microbit&quot;&gt;hardware&lt;/a&gt; &lt;a href=&quot;https://johnvidler.co.uk/blog/the-jacstack-an-addon-for-the-microbit&quot;&gt;prototypes&lt;/a&gt; to support our research at &lt;a href=&quot;https://www.lancaster.ac.uk/scc/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Lancaster University&lt;/a&gt; and towards the end of my tenure The Foundation comissioned a report on accessibility which included a speculative section on how to improve accessibility to the Micro:bit platform for folks with limited or different mobility.&lt;/p&gt;
&lt;h3 id=&quot;the-accessibility-survey&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/the-accessbit-an-accessibility-addon-for-the-microbit/#the-accessibility-survey&quot;&gt;The Accessibility Survey&lt;/a&gt;&lt;/h3&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/hardware/access-bit/b01-survey-01.jpg&quot; /&gt;
    &lt;figcaption&gt;Part of the internal report on Micro:bit hardware accessibility within The Foundation (reproduced with permission, May 2024)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;One of the key points that was highlighted was that for educators in a special needs situation the additional workload involved with making the devices and software accessible was layered on top of the already high workload in incorporating the Micro:bit into the classroom for non-domain experts (non-CS specific teachers). While training and resources are readily available for the Micro:bit, quite how far we put teachers outside their comfort zone should not be underestimated as a barrier to using the platform.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/hardware/access-bit/b02-survey-02.jpg&quot; /&gt;
    &lt;figcaption&gt;Part of the internal report on Micro:bit hardware accessibility within The Foundation (reproduced with permission, May 2024)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;To help with this, one of the suggestions from the report was to develop an addon for the Micro:bit that supported plugging directly into adaptive inputs (such as those used &lt;a href=&quot;https://www.xbox.com/en-GB/accessories/controllers/xbox-adaptive-controller&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;here for the XBox platform&lt;/a&gt;). These adaptive controls have settled on a de-facto standard based around 3.5mm audio jacks, of the sort commonly seen for ‘aux’ inputs in cars. These were picked for their general ubiquity and simple connection and disconnection action, as well as how robust they are.&lt;/p&gt;
&lt;h3 id=&quot;the-initial-design&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/the-accessbit-an-accessibility-addon-for-the-microbit/#the-initial-design&quot;&gt;The Initial Design&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;With this in mind, I set out to implement the ‘minimum viable board’ to achieve this with the specific goals in mind:&lt;/p&gt;
&lt;ol class=&quot;list&quot;&gt;
&lt;li&gt;Expose the A and B buttons to adaptive switches&lt;/li&gt;
&lt;li&gt;Expose the P0, P1, and P2 pins for input or output via adaptive interfaces&lt;/li&gt;
&lt;li&gt;No code changes should be required for this to work&lt;/li&gt;
&lt;li&gt;Manufacturing costs should be minimised&lt;/li&gt;
&lt;/ol&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/hardware/access-bit/Screenshot2024_04_08_214155.jpg&quot; /&gt;
    &lt;figcaption&gt;A super quick initial pass at reproducing the accessibility report sketches as a real PCB design. I really liked the little indents for each jack on this design, even if they were a pain to produce.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The above render is my first pass at achieving these goals; I simply connected each edge connector pin to the tip terminal on the jacks, connected the sleeve terminal to ground and labelled all the ports. This followed the design sketches from the report pretty closely, with the addition of indents around each jack socket to acommodate as many (potentially strangely shaped) jacks as possible.&lt;/p&gt;
&lt;p&gt;This I sent for review to Jonny at The Foundation as a proof of concept, and while he liked it, he and I both felt that this was maybe &lt;em&gt;too minimal&lt;/em&gt;, and that including some additional functionalty onto the board would be welcome.&lt;/p&gt;
&lt;p&gt;I’ve previously implemented the power and signal conditioning circuits to support &lt;a href=&quot;https://microsoft.github.io/jacdac-docs/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Jacdac&lt;/a&gt; on the Micro:bit for the &lt;a href=&quot;https://johnvidler.co.uk/blog/the-jacstack-an-addon-for-the-microbit/&quot;&gt;Jac:stack&lt;/a&gt;, and my collegue &lt;a href=&quot;https://mattoppenheim.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Matt Oppenheim&lt;/a&gt; has previously designed hardware to interface with other accessibility devices, so it made &lt;em&gt;a lot&lt;/em&gt; of sense to include this on the board as well.&lt;/p&gt;
&lt;p&gt;It also occurred to me that should the Micro:bit prove to be particularly useful to someone using it with this board, they may want to hard-mount it somehow for semi-permanent installtion, so having some mounting holes would be useful too.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/hardware/access-bit/Screenshot2024_04_10_224700.jpg&quot; /&gt;
    &lt;figcaption&gt;Jacdac you say? Well funny you should mention that...&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;One fairly quick re-spin of the original board, borrowing much of the circuitry from the Jac:stack resulted in the above, with two cable-type ports for Jacdac, and a redesigned silkscreen for the port labels (although I never did like the off-side labels of this design).&lt;/p&gt;
&lt;h3 id=&quot;meanwhile&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/the-accessbit-an-accessibility-addon-for-the-microbit/#meanwhile&quot;&gt;Meanwhile…&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Meanwhile, Jonny had an idea and sent me this concept drawing, which I will forever mentally refer to as ‘the grin’ design:&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/hardware/access-bit/access-bit-grin.jpg&quot; /&gt;
    &lt;figcaption&gt;From a short design review with Jonny at The Foundation, he suggested what I forever see as a big toothy grin variation of the board layout.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;But tooth-related mental images aside, having a curved input edge makes a lot of sense, as the spread of connectors are far less likely to interfere with one another in this configuration, and the board shape gains a reasonable amount of surface area without expanding the overall board dimensions too much.&lt;/p&gt;
&lt;h3 id=&quot;v3-curved-component-placement&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/the-accessbit-an-accessibility-addon-for-the-microbit/#v3-curved-component-placement&quot;&gt;V3 - Curved Component Placement&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I re-spun the board design again, this time with some angled inputs along a long curve:&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/hardware/access-bit/Screenshot2024_04_12_195631.jpg&quot; /&gt;
    &lt;figcaption&gt;Arcs in KiCAD are a bit... fun... to produce sometimes, but I managed an unrouted iteration to see how the layout would feel.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;This version 3.0 design came close to being the final one; and I spent a little while getting some polish done on the silkscreen and layout, as well as adding a few ‘nice to have’ features that didn’t add too much to the overall complexity and cost.&lt;/p&gt;
&lt;ul class=&quot;list&quot;&gt;
&lt;li&gt;An LED was added for each port, in-line with the jack&lt;/li&gt;
&lt;li&gt;The port labels were moved to be in-line with the jacks and replicated on the back of the board for additional visibility&lt;/li&gt;
&lt;li&gt;A silkscreen pictogram showing the connections required for the switches was added, to make the input self-documenting&lt;/li&gt;
&lt;li&gt;The addition of the Lancaster University and Micro:bit Foundation logos&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I even added the placeholder serial number location for my PCB fab house of choice &lt;a href=&quot;https://jlcpcb.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JLCPCB&lt;/a&gt; so short of actually building the manufacturing files this board was now ‘complete’!&lt;/p&gt;
&lt;figure&gt;
    &lt;figure&gt;
        &lt;img src=&quot;https://johnvidler.co.uk/assets/images/hardware/access-bit/Screenshot2024_04_15_135455.jpg&quot; /&gt;
        &lt;figcaption&gt;The v3 with activity LEDs on each pin, and a revised silkscreen&lt;/figcaption&gt;
    &lt;/figure&gt;
    &lt;figure&gt;
        &lt;img src=&quot;https://johnvidler.co.uk/assets/images/hardware/access-bit/Screenshot2024_04_15_135505.jpg&quot; /&gt;
        &lt;figcaption&gt;The rear of the v3, complete with a bit of self-documentation in the form of the silkscreen 3.5mm jack showing the connected pins.&lt;/figcaption&gt;
    &lt;/figure&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;fabrication-with-no-budget&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/the-accessbit-an-accessibility-addon-for-the-microbit/#fabrication-with-no-budget&quot;&gt;Fabrication With No Budget&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As this was just a side project I had no budget to actually have the boards fabricated, so I turned to another collegue, &lt;a href=&quot;https://www.lancaster.ac.uk/scc/about-us/people/steve-hodges&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Prof. Steve Hodges&lt;/a&gt; who graciously provided the funds, and also helped with a final design review. He noted that I had not included any &lt;a href=&quot;https://en.wikipedia.org/wiki/Transient-voltage-suppression_diode&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;TVS&lt;/a&gt; diodes on the inputs, as I had so far been relying on the Micro:bit’s designed-in protection for its edge connector; but as the parts to add would only be extremely low cost, I patched these in, along with the new &lt;a href=&quot;http://devices-lab.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Devices Lab&lt;/a&gt; logo, and called it v4 - ready to fab!&lt;/p&gt;
&lt;figure&gt;
    &lt;figure&gt;
        &lt;img src=&quot;https://johnvidler.co.uk/assets/images/hardware/access-bit/Screenshot2024_05_16_171044.jpg&quot; /&gt;
        &lt;figcaption&gt;The &#39;final&#39; v4 revision after a design review with Steve Hodges, with the inclusion of some additional TVS diodes on the GPIO pins just in case.&lt;/figcaption&gt;
    &lt;/figure&gt;
    &lt;figure&gt;
        &lt;img src=&quot;https://johnvidler.co.uk/assets/images/hardware/access-bit/Screenshot2024_05_16_171049.jpg&quot; /&gt;
        &lt;figcaption&gt;The read of the v4; now with a &lt;a href=&quot;https://devices-lab.org/&quot; target=&quot;_blank&quot;&gt;devices-lab.org&lt;/a&gt; copper logo and the &lt;a href=&quot;https://microbit.org/accessibility/&quot; target=&quot;_blank&quot;&gt;microbit.org accessibility pages&lt;/a&gt; URL&lt;/figcaption&gt;
    &lt;/figure&gt;
&lt;/figure&gt;
&lt;p&gt;Three days plus expedited shipping later, I had one in my hands - a real board &lt;em&gt;nearly&lt;/em&gt; complete! I elected to not include the large 40-pin Micro:bit connector, as JLCPCB don’t normally stock these, and it would have involved additional delays in them buying in the parts. Plus honestly with the aid of a cheap hot plate its very easy to get these soldered on by hand even without a solder stencil; a quick smear of low-temperature solder paste along the terminals and you can just drop the part onto the hot plate and 20 seconds later, you have a perfectly soldered connector. The only other remaining step was then to hand solder on the two connector mounting lugs on the back, the work again of only a few seconds.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/hardware/access-bit/assembled-board.png&quot; /&gt;
    &lt;figcaption&gt;The real thing, in glorious green FR4. I elected to not get JLCPCB to populate the large 40-pin microbit connector, as I would have to pay for them to stock this for me, and I do have a perfectly servicable hot plate setup...&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/hardware/access-bit/hotplate-smt.png&quot; /&gt;
    &lt;figcaption&gt;One quick application of some low-temperature solder paste and about 20 seconds on the hot place and we&#39;re pretty much done. I just need to hand solder the rear support lugs as well for extra stability. I don&#39;t do this on the plate, as it would put solder in direct contact with the hot plate surface.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;ready-to-ship!&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/the-accessbit-an-accessibility-addon-for-the-microbit/#ready-to-ship!&quot;&gt;Ready To Ship!&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I tested each port using my own &lt;a href=&quot;https://johnvidler.co.uk/blog/3d-printable-accessibility-switches/&quot;&gt;3D Printable Paddle Switch&lt;/a&gt; designs with all working perfectly (phew!)&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/hardware/access-bit/paddle-switch-test.png&quot; /&gt;
    &lt;figcaption&gt;At the time I only had one 3.5mm cable to hand (where the heck to these things hide?!?) but every port worked!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;So after some quick 3D printing, soldering and packing up they are now winging their way down to Cambridge just in time to go along to the &lt;a href=&quot;https://developers.google.com/blockly/summits/summits&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Blockly Summit &#39;24&lt;/a&gt;, where if you go along in person, you can try these out at the Micro:bit table.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/hardware/access-bit/shipping-out.jpg&quot; /&gt;
    &lt;figcaption&gt;Ready to go! Just in time for the &lt;a href=&quot;https://developers.google.com/blockly/summits/summits&quot; target=&quot;_blank&quot;&gt;Blockly Summit &#39;24&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;</content
    >
  </entry>
  <entry>
    <title>Docker 102</title>
    <link href="https://johnvidler.co.uk/blog/docker-102/" />
    <updated>2023-12-04T00:00:00Z</updated>
    <id>https://johnvidler.co.uk/blog/docker-102/</id>
    <content
      xml:lang=""
      type="html"
      >&lt;div class=&quot;note&quot;&gt;
Part of a (short) series on &#39;knowing enough to be dangerous&#39; with Docker.
&lt;/div&gt;
  &lt;div class=&quot;youtube-embed&quot;&gt; &lt;lite-youtube videoid=&quot;ilg__8KbjAE&quot; style=&quot;background-image: url(&#39;https://i.ytimg.com/vi/ilg__8KbjAE/hqdefault.jpg&#39;);&quot;&gt;
  &lt;button type=&quot;button&quot; class=&quot;lty-playbtn&quot;&gt;
    &lt;span class=&quot;lyt-visually-hidden&quot;&gt;Docker 102 - John Vidler&lt;/span&gt;
  &lt;/button&gt;
&lt;/lite-youtube&gt;&lt;/div&gt;
&lt;p&gt;John discusses various aspects of Docker in this video, including networking within containers, Docker Compose, troubleshooting Docker Compose, passing environment variables, running containers using Docker Compose, mounting volumes, and security issues. They provide explanations, examples, and demonstrations to help viewers understand and apply these concepts. John also emphasizes the benefits of using Docker, such as simplifying the process of running multiple containers together and reducing administration overhead. They conclude by offering to answer any questions from the audience.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://youtube.com/watch?v=ilg__8KbjAE&amp;amp;t=0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;00:00:00&lt;/a&gt;&lt;/strong&gt; In this section, John discusses the basic concepts of Docker and gives an overview of containerization and images. They also touch on networking within containers, including different ways to configure networking and the concept of isolation. John mentions that there are ways to poke holes in containers, particularly through networking and storage devices. They then dive deeper into networking concepts, including options such as none, host mode, bridge mode, and overlay mode. The focus is primarily on bridge mode, which is used for a single host.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://youtube.com/watch?v=ilg__8KbjAE&amp;amp;t=300&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;00:05:00&lt;/a&gt;&lt;/strong&gt; In this section, John explains the differences between bridge mode and overlay mode in Docker networking. Bridge mode is the default mode, where containers have a connection to the host and can connect to the outside world through Network Address Translation (NAT). However, by default, connections cannot be initiated from the outside world to the container. To allow incoming connections, port forwarding can be used. Overlay mode, on the other hand, is used in container orchestrators like Swarm, where containers running on different hosts can communicate with each other as if they were in bridge mode. This mode is commonly used in web applications where multiple containers need to serve web pages or web sockets. To handle multiple containers on the same port, a reverse proxy like Nginx is used to translate incoming connections to the appropriate container. This pattern is becoming more common in small setups, replacing the need for separate VMs for each website. However, when using port forwarding, it is important to be cautious as it opens the container to all connections.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://youtube.com/watch?v=ilg__8KbjAE&amp;amp;t=600&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;00:10:00&lt;/a&gt;&lt;/strong&gt; In this section, John discusses Docker compose, which is a tool used to describe the arrangement of containers and pass along configurations in a repeatable way. Docker compose is based on yaml files and John provides an example of a Docker compose file. The file includes a version at the top level and a Services block, which lists the containers to be run. John explains the different configurations for a container, such as the image, restart policy, and environment variables. Overall, Docker compose simplifies the process of running multiple containers together.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://youtube.com/watch?v=ilg__8KbjAE&amp;amp;t=900&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;00:15:00&lt;/a&gt;&lt;/strong&gt; In this section, John explains how to set up another instance using Docker Compose for PHP my admin. They specify the container name, image, and restart setting. To allow external interface, they open the port and set an environment variable. They also add a “depends on” stanza to ensure that PHP my admin only starts if there is a database to connect to. John demonstrates how to run the Docker Compose command and explains that the PHP my admin container has a complex image with various web configurations. The process involves downloading and eventually completing the setup.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://youtube.com/watch?v=ilg__8KbjAE&amp;amp;t=1200&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;00:20:00&lt;/a&gt;&lt;/strong&gt; In this section, John and the audience members are troubleshooting issues with Docker Compose while trying to run a demo. They discuss possible solutions, such as checking file names and ensuring that Docker Compose is installed properly. The demo seems to be broken due to a typo in the Docker Compose file, causing the container to not start. Eventually, they discover that the root password needs to be modified for the MySQL container. Despite the challenges, they hope that the adjustments made will resolve the issues and allow for a successful demo.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://youtube.com/watch?v=ilg__8KbjAE&amp;amp;t=1500&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;00:25:00&lt;/a&gt;&lt;/strong&gt; In this section of the video, John discusses the progress of running the Docker containers and encountering some errors along the way. They mention the need to make some changes, such as adding quotes and being mindful of system updates and changes. Eventually, they are able to get the containers running successfully. They also explain how to check the running containers using the Docker PS command and note the mapping of ports. John then mentions the use of environment variables to pass parameters into the containers and explains the syntax and persistence of these variables. Finally, they highlight the need for a more streamlined and secure setup, suggesting the use of additional configuration options.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://youtube.com/watch?v=ilg__8KbjAE&amp;amp;t=1800&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;00:30:00&lt;/a&gt;&lt;/strong&gt; In this section, the video discusses how to pass environment variables to Docker containers using Docker Compose. By using the dollar bracket syntax in the YAML file, users can replace values with environment variables. This allows for flexibility and customization when running containers. In addition, the video explains how to set default values and error messages for environment variables. The example given shows how to replace a MySQL root password with an environment variable, ensuring that sensitive information is not exposed. The video also mentions the importance of securing containers by specifying the interface to listen to. Lastly, the video demonstrates how to specify environment variables for accessing PHPMyAdmin. Overall, this section provides useful information on how to manage environment variables in Docker Compose.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://youtube.com/watch?v=ilg__8KbjAE&amp;amp;t=2100&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;00:35:00&lt;/a&gt;&lt;/strong&gt; In this section of the video, John discusses how to run Docker compose commands to start containers and set passwords. They explain that running the containers in the background can be done by adding a “-d” flag to the command. They also mention the importance of binding the containers to only the host machine to prevent unauthorized access to the database. John then introduces the concept of mounting volumes to store data outside of the containers, specifically mentioning the ability to connect to remote stores like AWS. They explain that volumes can be set to read-only or read-write modes and provide an example of how to add a volume to the Docker compose file. Overall, this section focuses on the practical aspects of running and managing containers in Docker.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://youtube.com/watch?v=ilg__8KbjAE&amp;amp;t=2400&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;00:40:00&lt;/a&gt;&lt;/strong&gt; In this section, John discusses the different ways to mount volumes in Docker. They mention that bind mounts are the most common for development purposes since they allow connecting to files on the host machine. However, for orchestrated larger networks with multiple hosts, it is important to consult the hosts to see how they want volumes to be mounted. John also introduces the concept of Docker volumes, which are managed by Docker itself and can be shared between containers. They briefly touch on the benefits of using volumes and mention that they can be explored further at a later time. Finally, John provides instructions on how to set up a folder for data using Docker Compose and verifies that the data persists even after stopping and starting the containers. They encourage further exploration of Docker images on Docker Hub and recommend looking at the Docker Compose reference for more in-depth guidance.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://youtube.com/watch?v=ilg__8KbjAE&amp;amp;t=2700&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;00:45:00&lt;/a&gt;&lt;/strong&gt; In this section, John discusses security issues with outdated virtual machines (VMs) and the need for container templates for common configurations. They mention the goal of having a ready-made website integrated with gitlab, allowing users to easily copy a repository and have it built and deployed seamlessly. This approach is intended to reduce the administration overhead associated with VMs. John concludes by expressing gratitude for the audience’s attention and offering to answer any questions.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Summary text originally from &lt;a href=&quot;https://www.summarize.tech/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;summarize.tech&lt;/a&gt; with light post editing.&lt;/p&gt;
</content
    >
  </entry>
  <entry>
    <title>Docker 101</title>
    <link href="https://johnvidler.co.uk/blog/docker-101/" />
    <updated>2023-12-03T00:00:00Z</updated>
    <id>https://johnvidler.co.uk/blog/docker-101/</id>
    <content
      xml:lang=""
      type="html"
      >&lt;div class=&quot;note&quot;&gt;
Part of a (short) series on &#39;knowing enough to be dangerous&#39; with Docker.
&lt;/div&gt;
  &lt;div class=&quot;youtube-embed&quot;&gt; &lt;lite-youtube videoid=&quot;0_SjIlpuSD8&quot; style=&quot;background-image: url(&#39;https://i.ytimg.com/vi/0_SjIlpuSD8/hqdefault.jpg&#39;);&quot;&gt;
  &lt;button type=&quot;button&quot; class=&quot;lty-playbtn&quot;&gt;
    &lt;span class=&quot;lyt-visually-hidden&quot;&gt;Docker 101 - John Vidler&lt;/span&gt;
  &lt;/button&gt;
&lt;/lite-youtube&gt;&lt;/div&gt;
&lt;p&gt;In this YouTube video titled “Docker 101,” John provides an introduction to Docker and its importance in simplifying the deployment process. They explain the concept of Docker containers, which are loosely isolated environments that contain all the necessary requirements for an application to run. John demonstrates how to build and run containers using Docker, using Python as an example. They also discuss the use of Docker Hub, a repository for Docker images, and explain the concept of Dockerfiles, which are recipes for creating Docker images. John then covers topics like exposing ports, running multiple containers using Docker Compose, and the option of uploading images to Docker Hub for sharing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://youtube.com/watch?v=0_SjIlpuSD8&amp;amp;t=0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;00:00:00&lt;/a&gt;&lt;/strong&gt; In this section, John is introducing himself and explaining the requirements for following along with the presentation. He also provides an overview of the topics that will be covered, including why Docker is important, example workflows, and the basics of Docker containers. John emphasizes the ability of Docker to isolate applications and simplify the deployment process. He also mentions that he will be discussing building custom Docker images and Dockerfile basics in later parts of the presentation. The section concludes with John sharing examples of traditional workflows and explaining how Docker can simplify the process by isolating dependencies.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://youtube.com/watch?v=0_SjIlpuSD8&amp;amp;t=300&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;00:05:00&lt;/a&gt;&lt;/strong&gt; In this section, John discusses the challenges of software distribution and the concept of dependency hell, where different libraries and systems have varying dependencies, leading to a nightmarish experience. John mentions workarounds like using virtual machines or packaging applications with their libraries. However, Docker provides a simpler solution by removing the need for host configuration and runtime requirements, without requiring a heavyweight virtual machine. Docker creates a Loosely isolated environment called a container, which contains all the necessary requirements for an application to run, making software distribution much easier and efficient.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://youtube.com/watch?v=0_SjIlpuSD8&amp;amp;t=600&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;00:10:00&lt;/a&gt;&lt;/strong&gt; In this section, the concept of containers is introduced. Containers are described as loosely isolated environments that are similar to virtual machines but much lighter. While virtual machines isolate every aspect of the hardware they are running on, containers only care about the necessary functionalities like network connections. Containers aim to keep instances isolated from the host environment to avoid interference. They are based on read-only templates called images, which serve as the initial state of a container. Images are built on top of one another, with the top layer usually representing the application. It is recommended to keep the stack of layers as short as possible to maintain a lightweight image. The difference between traditional virtual machines and containerized architectures is also explained, highlighting the shorter stack and minimal extras in containers. The goal is always to make containers thinner, with only the necessary components included.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://youtube.com/watch?v=0_SjIlpuSD8&amp;amp;t=900&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;00:15:00&lt;/a&gt;&lt;/strong&gt; In this section, John introduces the “play along at home” portion of the tutorial where they will demonstrate building web-based containers using Python. They mention that Python knowledge is not required as the necessary files have already been provided. John also suggests using other languages such as Perl or PHP if preferred. They explain that they will be building a container in Alpine Linux and highlight its small size, making it ideal for demos. John demonstrates running Alpine Linux in Docker and explains that they are operating as root since there are no users included in the image. They also mention that the Alpine Linux image is approximately 7MB in size. John asks for confirmation from the audience if they have successfully set up Docker and invites questions or comments. They explain the concept of the unique hash associated with each layer and that Docker builds containers by stacking these layers in order. They clarify that an internet connection is required to download the necessary Docker images.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://youtube.com/watch?v=0_SjIlpuSD8&amp;amp;t=1200&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;00:20:00&lt;/a&gt;&lt;/strong&gt; In this section, John discusses the need to eliminate unnecessary Docker images in order to avoid storage issues. They explain how Docker maintains a cache of images, which can accumulate over time if not deleted. John also provides a demonstration of how to clean up Docker images. Additionally, John explains that Alpine Linux, which is used in Docker, is a minimal operating system that runs very few processes and requires less memory compared to other operating systems like Ubuntu. John also mentions the ability to configure Docker to utilize specific resources, such as a limited number of cores. Lastly, there is a brief discussion about running Docker on Windows and the recommendation to use CMD for Windows users.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://youtube.com/watch?v=0_SjIlpuSD8&amp;amp;t=1500&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;00:25:00&lt;/a&gt;&lt;/strong&gt; In this section, John explains how to check if you are inside the Alpine Linux container and how to access your running containers. They mention that if you see the slash hash prompt, then you are inside Alpine. They also explain that the Docker PS command is equivalent to the PS command for Linux and it displays the running containers. John demonstrates how to exit the container and return to the host. They also mention that ending the container’s operation does not remove it, and you can use Docker PS -a to see both running and non-running containers. Finally, they discuss how to remove containers and images, and suggest using Docker system prune to clean up.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://youtube.com/watch?v=0_SjIlpuSD8&amp;amp;t=1800&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;00:30:00&lt;/a&gt;&lt;/strong&gt; In this section of the video, John demonstrates how to manually remove a Docker container by using the Docker RM command followed by either the container ID or name. It is important to note that this command only removes the running instance of the container, not the container image itself. John also mentions the use of the Docker prune command to remove multiple containers at once. They advise using the “–RM” flag when running a container if it is meant to be temporary and should be deleted once it is stopped. John recommends being cautious when using the RM flag and suggests not relying on it for important tasks. They then move on to discussing how to run Python in a Docker container using different image variants and tags.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://youtube.com/watch?v=0_SjIlpuSD8&amp;amp;t=2100&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;00:35:00&lt;/a&gt;&lt;/strong&gt; In this section of the video, John introduces Docker Hub, a repository for Docker images. They explain that by visiting &lt;a href=&quot;http://hub.docca.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;hub.docca.com&lt;/a&gt; and navigating to the Python section, users can find various Python versions available for use. John notes that there are simple tags and variations of Python available, including different versions for different operating systems like Debian and Ubuntu. They mention that these images on Docker Hub are safe to use, as they are official Docker images. John also discusses the concept of Dockerfiles, which are recipes for creating Docker images. They explain that Dockerfiles contain a series of steps that configure the final image. John goes through a sample Dockerfile, explaining each directive and the order in which they are executed. They mention that the Dockerfile specifies the base image (in this case, Ubuntu) and sets the working directory. John concludes by emphasizing that Dockerfiles are used for the static parts of a container and not for runtime requirements.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://youtube.com/watch?v=0_SjIlpuSD8&amp;amp;t=2400&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;00:40:00&lt;/a&gt;&lt;/strong&gt; In this section, John explains the use of the “copy” and “expose” directives in a Dockerfile. The “copy” directive is used to copy files from the host to the image, and it can be used to copy between different containers as well. The “expose” directive is used to specify which ports the image will listen on when it is run as a container. John also mentions that the “expose” directive is often used by management interfaces to determine the ports on which the container is running.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://youtube.com/watch?v=0_SjIlpuSD8&amp;amp;t=2700&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;00:45:00&lt;/a&gt;&lt;/strong&gt; In this section of the video, John discusses various aspects of Docker, including exposing ports and running containers. They explain that when running a container, it is important to specify the correct ports so that communication is possible. They also mention that the “work directory” can be customized, allowing the user to switch between different directories as needed. John emphasizes the recommended way of creating commands in Docker, which involves using arrays or lists. They demonstrate how to build a container using the Docker build command and explain the significance of the dot (.) in the command, which indicates that the build should occur in the current folder. John also highlights the importance of the order in which dependencies are specified in the Docker file, as it can significantly impact the build time. They mention that if one of the dependencies is large, it is best to include it early in the file to optimize the build process. Towards the end, John explains how to run a container and open the necessary ports to access a web interface. They provide instructions on connecting to the container using a web browser and show a simple Python web page that can be accessed. Finally, they mention that in the next part of the video, they will discuss accessing host files and transferring files to and from the container during runtime.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://youtube.com/watch?v=0_SjIlpuSD8&amp;amp;t=3000&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;00:50:00&lt;/a&gt;&lt;/strong&gt; In this section, John discusses Docker compose and how it can be used to run multiple containers simultaneously, which is the first step in container orchestration. They mention examples such as running a MySQL server, PHP MySQL admin, and a web interface together. John also mentions the option of uploading images to Docker Hub for sharing, or sharing it through Source by having it on GitHub. They briefly mention the possibility of doing multi-arch images in part four and hint at discussing cloud deployment in part three. John wraps up by acknowledging that the access log is almost complete and invites any questions from the audience.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Summary text originally from &lt;a href=&quot;https://www.summarize.tech/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;summarize.tech&lt;/a&gt; with light post editing.&lt;/p&gt;
</content
    >
  </entry>
  <entry>
    <title>Federated Web Rings and Link Sharing</title>
    <link href="https://johnvidler.co.uk/blog/federated-web-rings-and-link-sharing/" />
    <updated>2023-09-12T00:00:00Z</updated>
    <id>https://johnvidler.co.uk/blog/federated-web-rings-and-link-sharing/</id>
    <content
      xml:lang=""
      type="html"
      >&lt;p&gt;Historically I have struggled to maintain a decent list of bookmarks in any browser - for some reason putting them in the browser just means that I immediately forget that they exist at all, making the whole exercise rather pointless. So on the previous iteration of my website, I instead managed a list of links to resources that I commonly enough used, but did so infrequently enough that I would forget they existed before needing them again.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/code/webgraph-2.png&quot; class=&quot;bordered small&quot; /&gt;
    &lt;figcaption&gt;All your links are belong to me; collecting a link&#39;s link-list to make more links in our list! Alternatively &#39;its links all the way down&#39;...&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;This works well enough for me and could act as a bit of a directory for others, but I thought “wouldn’t it be neat if we could &lt;em&gt;all&lt;/em&gt; work on a big curated list of links we individually found interesting, then have them automatically joined together for indexing and searching?” - and yes slightly younger me, it would indeed. The mechanics for this to work are pretty simple too; if we know where a ‘far’ site keeps its list, and we agree on a format, we can wander &lt;em&gt;that&lt;/em&gt; list as well, then; using that list we can wander the new links, and so forth until we have a complete list, or get bored following links.&lt;/p&gt;
&lt;p&gt;This results in a kind of ‘federated link directory’ with hand picked links that folks have discovered over time, and from wherever you enter the graph from, you get only URLs that are federated from another peer, and so get slightly different resultant list views. With the addition of a few ‘core’ peers acting as master-ish lists, you can also get a pretty complete view of the whole network.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/code/webgraph-7.png&quot; class=&quot;bordered small&quot; /&gt;
    &lt;figcaption&gt;Around and around, individual sites may link to one another, and back again, so some sensible &#39;do not duplicate&#39; rules are needed when spidering, but otherwise there shouldn&#39;t be much problem with recursion.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;So I set out to implement this on my site here, so starting with a JSON object, where &lt;em&gt;each key is a link at the top level&lt;/em&gt;; we end up with the simplest implementation like so:&lt;/p&gt;
&lt;pre class=&quot;language-plaintext&quot;&gt;&lt;code class=&quot;language-plaintext&quot;&gt;{
    &quot;https://example.co.uk&quot;: {}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The file should exist at &lt;a href=&quot;https://johnvidler.co.uk/webgraph.json&quot;&gt;/webgraph.json&lt;/a&gt; (by convention) but can be overridden by setting the &lt;code&gt;webgraph&lt;/code&gt; property for a link entry.&lt;/p&gt;
&lt;p&gt;As each link is an object, we can then add optional metadata to each one, allowing us to refine the entry, so a more complex example for a single site might look like this:&lt;/p&gt;
&lt;pre class=&quot;language-plaintext&quot;&gt;&lt;code class=&quot;language-plaintext&quot;&gt;{
    &quot;https://example.com&quot;: {
        &quot;title&quot;: &quot;An example website&quot;,
        &quot;tags&quot;: [ &quot;example&quot;, &quot;web&quot;, &quot;testing&quot; ],
        &quot;description&quot;: &quot;This is just an example website, used mostly for testing&quot;,
        &quot;webgraph&quot;: &quot;my-cool-webgraph.json&quot;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The individual properties and their types are described below.&lt;/p&gt;
&lt;p&gt;The entries in this object can then be used in a couple of ways:&lt;/p&gt;
&lt;ul class=&quot;list&quot;&gt;
&lt;li&gt;The ‘local’ site can use this to generate a links page, to just have a public set of bookmarks without spidering at all; this is the simplest case.&lt;/li&gt;
&lt;li&gt;Any WebGraph spider that gets linked to the JSON can now add the links to its directory, and also follow them if they’re defined as having additional graph files.&lt;/li&gt;
&lt;li&gt;A WebGraph spider can use the data here to build a more interactive, searchable list of links for a bigger directory.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’ve implemented a proof-of-concept spider over at &lt;a href=&quot;https://johnvidler.co.uk/webgraph&quot;&gt;the WebGraph page on this site&lt;/a&gt; which will attempt to check the graph periodically and update a simple directory list of links. In the future I’d like to expand this to include search functions, but for now it just presents everything in a flat list.&lt;/p&gt;
&lt;h3 id=&quot;optional-properties&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/federated-web-rings-and-link-sharing/#optional-properties&quot;&gt;Optional Properties&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;&amp;quot;webgraph&amp;quot;: &amp;quot;/webgraph.json&amp;quot;&lt;/code&gt; A site-local path; the WebGraph URL. If omitted this site is not wandered to build the link graph.&lt;/p&gt;
&lt;p&gt;Its worth noting that this does not have to be a bare .json file, but could just as easily be any other valid URL that returns a JSON object. For smaller sites I envisage that the authors would maintain their own .json file and just serve this, parsing it to generate their own link lists on their local site, but for larger indexes this could easily be pulled from a database, or autogenerated from crawling internal pages for external links, for example.&lt;/p&gt;
&lt;p&gt;I realise that this could theoretically become extremely large, especially if there are any consolidating sites that rebuild their webgraph data as they spider, however I’m leaving this problem for ‘future John’ for now, as I’d like to see if this experiment works at all first. The graph could fairly easily be paginated however, with the addition of some kind of GET arg like &lt;code&gt;?p=2&lt;/code&gt; for ‘page 2’ for example, although this would also require that the API exposed had some way of defining an upper limit for how many pages it could serve (unless we just pull until the request fails, but that feels &lt;em&gt;bad&lt;/em&gt; to me).&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;quot;title&amp;quot;: &amp;quot;The Homepage of Cool Mc&#39;Dude&amp;quot;&lt;/code&gt; A string. The title string, otherwise the URL should be used in place of a title.&lt;/p&gt;
&lt;p&gt;I might scrape this from the link URL later if this property is missing, but this will override that behaviour in any case. Note that &lt;em&gt;right now&lt;/em&gt; the spider on this site will use the lexographically-ordered first-found entry for a given site, and drop any other subsequent duplicates. In the future I expect I’ll collect them all then pick the ‘best’ (for various definitions of best) value for these to display, but this behaviour is entirely up to the spider. If you don’t like the behaviour seen here, then do feel free to implement your spider however you like!&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;quot;tags&amp;quot;: [ &amp;quot;friends&amp;quot;, &amp;quot;cool&amp;quot;, &amp;quot;dude&amp;quot; ]&lt;/code&gt; A flat string array. This is just a simple list of free-form tags, which are later collated by the spider to build tagged link groups.&lt;/p&gt;
&lt;p&gt;This can be used in any number of ways to group links together; perhaps by country, language or region (indeed, many of my own so far have ISO country code tags), or perhaps by topic or ‘#hashtag’ maybe? I leave the specific uses of the tags for the network itself to resolve, and that they merely act as a loose way to group links together.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;quot;description&amp;quot;: &amp;quot;Some cool person&#39;s site!&amp;quot;&lt;/code&gt; A free-form string, providing a description for this URL. My spider on this site will attempt to display this if it is present, although it will filter the content if it is excessively long (actual max length to be defined) or contains bad characters (already filtered for all common ones).&lt;/p&gt;
&lt;h3 id=&quot;properties-subject-to-change&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/federated-web-rings-and-link-sharing/#properties-subject-to-change&quot;&gt;Properties Subject to Change&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;&amp;quot;feed&amp;quot;: &amp;quot;/feed.xml&amp;quot;&lt;/code&gt; A site-local path. This can be an rss feed, or sitemap.xml or equivalent schema, wandered to populate sub-page lists if present, or skipped if omitted.&lt;br /&gt;
I’m a little on the fence about this one, and it may well change to individual typed definitions, with a distinct &lt;code&gt;sitemap&lt;/code&gt; and &lt;code&gt;rss&lt;/code&gt; options for those types. Perhaps I should include this as sub-property of the larger object for a site, maybe under a &lt;code&gt;meta&lt;/code&gt; key, to prevent namespace pollution.&lt;/p&gt;
&lt;p&gt;Feel free to tell me I’m wrong in the comments below.&lt;/p&gt;
</content
    >
  </entry>
  <entry>
    <title>More on Mastodon Comments</title>
    <link href="https://johnvidler.co.uk/blog/more-on-mastodon-comments/" />
    <updated>2023-08-24T00:00:00Z</updated>
    <id>https://johnvidler.co.uk/blog/more-on-mastodon-comments/</id>
    <content
      xml:lang=""
      type="html"
      >&lt;div class=&quot;note&quot;&gt;This post uses interactive code blocks! Feel free to edit and experiment with the code. All code listings here are MIT licensed with no warranty.&lt;/div&gt;
&lt;p&gt;In my previous post, I demonstrated Mastodon comments being used for in-page discussions on this website, but didn’t explain how it worked. (Honestly, the post was &lt;em&gt;barely&lt;/em&gt; a post and just demonstrated the concept)&lt;/p&gt;
&lt;h3 id=&quot;so-how-does-it-work&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/more-on-mastodon-comments/#so-how-does-it-work&quot;&gt;So how does it work?&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The Mastodon API has an extremely handy function &lt;code&gt;context&lt;/code&gt; for a given &lt;code&gt;status&lt;/code&gt;, with which we can ask a Mastodon instance to give us all the ancestors and descendants for a specific status.&lt;/p&gt;
&lt;p&gt;By taking the public post URL, we can split out the domain and comment id:&lt;/p&gt;
&lt;pre class=&quot;language-plaintext&quot;&gt;&lt;code class=&quot;language-plaintext&quot;&gt;URL    = https://fediscience.org/@johnvidler/110921679945683327
Domain = ^^^^^^^^^^^^^^^^^^^^^^^
UID    =                                     ^^^^^^^^^^^^^^^^^^&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Somewhat strangely, we don’t need the username… but anyway, we can then reconstruct this into a REST API address like so:&lt;/p&gt;
&lt;pre class=&quot;language-plaintext&quot;&gt;&lt;code class=&quot;language-plaintext&quot;&gt;REST URL = https://fediscience.org/api/v1/statuses/110921679945683327/context
Domain   = ^^^^^^^^^^^^^^^^^^^^^^^
UID      =                                         ^^^^^^^^^^^^^^^^^^&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;An in-browser demonstration for the previous post’s comments is shown here; click ‘Run’ to see the data.&lt;/p&gt;
&lt;script type=&quot;text/notebook-cell&quot;&gt;
const response = await fetch( &quot;https://fediscience.org/api/v1/statuses/110921679945683327/context&quot; );
const data = await response.json();
console.log( JSON.stringify( data, null, &#39; &#39; ) );
&lt;/script&gt;
&lt;p&gt;Unfortunately, the statuses are returned in a flat list (in time order), and ideally we’d like to be able to do comment threading where the parent comment has its replies as part of the parent context, so we can recursively render the reply list and get the nested comments seen on the previous post.&lt;/p&gt;
&lt;p&gt;To do this, I threw together the &lt;code&gt;treeifyComments&lt;/code&gt; which recursively wanders a tree structure looking for where the status property &lt;code&gt;in_reply_to_id&lt;/code&gt; matches a node, and adds the status to the node’s &lt;code&gt;replies&lt;/code&gt; list, with a few fallbacks for cases where no mapping can be found.&lt;/p&gt;
&lt;p&gt;The following code is an annotated version of this function, and if you click ‘Run’ it will populate the &lt;code&gt;root&lt;/code&gt; object with a nested set of comments.&lt;/p&gt;
&lt;script type=&quot;text/notebook-cell&quot;&gt;
function treeifyComments( node, comment, isRoot = true ) {
    // Ensure we _always_ have a replies array
    node.replies = node.replies || [];

    // Is this the node we&#39;re looking for?
    if( node.id == comment.in_reply_to_id ) {

        // Check that we don&#39;t already have a copy in our replies array (an 11ty.dev specific thing!)
        if( !node.replies.some( v =&gt; v.id == comment.id ) )
            node.replies.push( comment );
        
        // Let the caller know we&#39;re done
        return true;
    }

    // Otherwise, wander through all our replies, calling ourselves with the reply node
    for( const idx in node.replies ) {

        // If one of our replies (or their replies) found where this comment should go, cool, just return
        if( treeifyComments( node.replies[idx], comment, false ) )
            return true;
    }

    // Otherwise we couldn&#39;t find the ID referenced anywhere, so if we&#39;re root, just add it.
    if( isRoot ) {
        node.replies.push( comment );
        return true;
    }

    return false;
}

const response = await fetch( &quot;https://fediscience.org/api/v1/statuses/110921679945683327/context&quot; );
const data = await response.json();

const root = { id:0, replies:[] };
data.descendants.forEach( s =&gt; treeifyComments(root, s) );

console.log( JSON.stringify( root, null, &#39; &#39; ) );
&lt;/script&gt;
&lt;p&gt;With this structure loaded (and cached by my static build system to keep requests infrequent!) we can now render this into a series of nested &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;s and style it to our hearts content.&lt;/p&gt;
&lt;p&gt;Taa-daa!&lt;/p&gt;
&lt;p&gt;If you have questions, do reach out via the links below.&lt;/p&gt;
</content
    >
  </entry>
  <entry>
    <title>Mastodon Comments</title>
    <link href="https://johnvidler.co.uk/blog/mastodon-comments/" />
    <updated>2023-08-19T00:00:00Z</updated>
    <id>https://johnvidler.co.uk/blog/mastodon-comments/</id>
    <content
      xml:lang=""
      type="html"
      >&lt;p&gt;I’ve been continuing to rework my site lately, and have just thrown together a basic integration with Mastodon for post comments. Hopefully if you reply to &lt;a href=&quot;https://fediscience.org/@johnvidler/110921679945683327&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;this status&lt;/a&gt;, it should be picked up on the website on the next check (usually every 24hrs)&lt;/p&gt;
&lt;p&gt;If it works, your comments should show up down below!&lt;/p&gt;
</content
    >
  </entry>
  <entry>
    <title>Makecode Block Annotations</title>
    <link href="https://johnvidler.co.uk/blog/makecode-block-annotations/" />
    <updated>2023-08-13T00:00:00Z</updated>
    <id>https://johnvidler.co.uk/blog/makecode-block-annotations/</id>
    <content
      xml:lang=""
      type="html"
      >&lt;p&gt;This is a slowly growing list of annotations for blocks in Makecode, mostly to document these for myself whenever I need to write another extensions.&lt;/p&gt;
&lt;h2 id=&quot;working-annotations&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/makecode-block-annotations/#working-annotations&quot;&gt;Working Annotations&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;These are annotations that I have seen work in practice.&lt;/p&gt;
&lt;h3 id=&quot;namespace-properties&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/makecode-block-annotations/#namespace-properties&quot;&gt;Namespace Properties&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;//% color=&amp;quot;#BC986A&amp;quot; icon=&amp;quot;&#92;uf0ea&amp;quot;&lt;/code&gt;&lt;br /&gt;
Change the colour and icon for the namespace - the icon appears to be most valid unicode characters…&lt;/p&gt;
&lt;h3 id=&quot;basic-block-properties&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/makecode-block-annotations/#basic-block-properties&quot;&gt;Basic Block Properties&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Block Body Text&lt;/strong&gt;&lt;br /&gt;
&lt;code&gt;//% block=&amp;quot;block text here&amp;quot;&lt;/code&gt;&lt;br /&gt;
This will replace the default generated block text with the supplied text.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Menu Groups&lt;/strong&gt;&lt;br /&gt;
&lt;code&gt;//% group=&amp;quot;Buttons&amp;quot;&lt;/code&gt;&lt;br /&gt;
This does not require that the groups be predefined in the namespace.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Place Parameters in the Body Text&lt;/strong&gt;&lt;br /&gt;
&lt;code&gt;//% block=&amp;quot;on ClipBit button $button pressed&amp;quot;&lt;/code&gt;&lt;br /&gt;
Replace $-prefix words with their parameter from the function.&lt;br /&gt;
Note that enums will be rendered as their names, rather than their values.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Advanced Blocks - Menu UI&lt;/strong&gt;&lt;br /&gt;
&lt;code&gt;//% advanced=&amp;quot;true&amp;quot;&lt;/code&gt;&lt;br /&gt;
Move the block to the &lt;code&gt;more&lt;/code&gt; section below the main section in the extension menu.&lt;/p&gt;
&lt;h3 id=&quot;parameter-render-options&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/makecode-block-annotations/#parameter-render-options&quot;&gt;Parameter Render Options&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Boolean Switches&lt;/strong&gt;&lt;br /&gt;
&lt;code&gt;//% on.shadow=&amp;quot;toggleOnOff&amp;quot;&lt;/code&gt;&lt;br /&gt;
Sets the parameter ‘on’ to use the toggle on/off UI rather an a variable slot&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Expandable Blocks (Hidden Parameters)&lt;/strong&gt;&lt;br /&gt;
&lt;code&gt;//% block=&amp;quot;set ClipBit $display display to $value || as $style&amp;quot;&lt;/code&gt;&lt;br /&gt;
The double-bar &lt;code&gt;||&lt;/code&gt; indicates the point that the block UI will be split, and replaced with an expander &lt;code&gt;+&lt;/code&gt; icon.&lt;/p&gt;
&lt;h3 id=&quot;properties-for-event-handlers&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/makecode-block-annotations/#properties-for-event-handlers&quot;&gt;Properties for Event Handlers&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Allow Dragging of Parameters&lt;/strong&gt;&lt;br /&gt;
&lt;code&gt;//% draggableParameters=&amp;quot;reporter&amp;quot;&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&quot;moving-between-languages&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/makecode-block-annotations/#moving-between-languages&quot;&gt;Moving Between Languages&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Shims&lt;/strong&gt;&lt;br /&gt;
&lt;code&gt;//% shim=ClipBit::sendLogViaSerial&lt;/code&gt;&lt;br /&gt;
Map the exported function annotated with this to the C++ call defined in the &lt;code&gt;shim&lt;/code&gt;. Note that this doesn’t make a block by itself, and just exposes the call to Typescript.&lt;br /&gt;
If the function in Typescript has a body, this will be used in the sim.&lt;/p&gt;
&lt;h2 id=&quot;non-working-annotations&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/makecode-block-annotations/#non-working-annotations&quot;&gt;Non-working Annotations&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;These are annotations that don’t seem to work correctly for Makecode extensions&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Grid Picker&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-plaintext&quot;&gt;&lt;code class=&quot;language-plaintext&quot;&gt;//% name.fieldEditor=&quot;gridpicker&quot;
//% name.fieldOptions.columns=4
//% name.fieldOptions.tooltips=&quot;false&quot;
//% name.fieldOptions.width=&quot;250&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This (as seen in &lt;a href=&quot;https://github.com/microsoft/pxt-microbit/blob/958401e2ee74e93848d6aae14d503bda72c0fba8/libs/core/pins.cpp#L256&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;pxt-microbit here&lt;/a&gt;) seems to enumerate enum values and generate a grid of buttons rather than the usual dropdown, except that it doesn’t work for extensions? Specifying these paramters will result in the block not having any parameter for the user to select at all!&lt;/p&gt;
&lt;hr /&gt;
&lt;h3 id=&quot;updated-5/2/2024&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/makecode-block-annotations/#updated-5/2/2024&quot;&gt;Updated 5/2/2024&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you don’t actually want to have a block show up, but need the c++ shim to be generated, the correct way now seems to be to include &lt;code&gt;//% &lt;/code&gt; as a comment before the methods you want to export.&lt;/p&gt;
&lt;p&gt;With no directives, this just generates the shims and makes the compiler happy again.&lt;/p&gt;
</content
    >
  </entry>
  <entry>
    <title>Bee Photography</title>
    <link href="https://johnvidler.co.uk/blog/bee-photography/" />
    <updated>2023-08-03T00:00:00Z</updated>
    <id>https://johnvidler.co.uk/blog/bee-photography/</id>
    <content
      xml:lang=""
      type="html"
      >&lt;p&gt;I don’t have any decent cameras, just my mobile phone (Currently a Google Pixel 5), but sometimes I do manage to get a half-decent shot or two, and apparently the one thing that this phone is particularly good at is macro photos.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/photos/bee_001.png&quot; /&gt;
    &lt;figcaption&gt;A close up photograph of a bee!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;There are a rather large number of bees buzzing around the flowers outside my office right now, so I took the opportunity and managed a few decent shots.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/photos/bee_002.png&quot; /&gt;
    &lt;figcaption&gt;Another bee, stepping from flower to flower&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/photos/bee_003.png&quot; /&gt;
    &lt;figcaption&gt;A bee face-deep into a flower&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/photos/bee_004.png&quot; /&gt;
    &lt;figcaption&gt;A bee about to be face-deep into a flower&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/photos/bee_005.png&quot; /&gt;
    &lt;figcaption&gt;A bee investigating small clusters of flowers&lt;/figcaption&gt;
&lt;/figure&gt;</content
    >
  </entry>
  <entry>
    <title>Chicago Photography</title>
    <link href="https://johnvidler.co.uk/blog/chicago-photography/" />
    <updated>2023-07-26T00:00:00Z</updated>
    <id>https://johnvidler.co.uk/blog/chicago-photography/</id>
    <content
      xml:lang=""
      type="html"
      >&lt;p&gt;I don’t have any decent cameras, just my mobile phone (Currently a Google Pixel 5), but sometimes I do manage to get a half-decent shot or two. In this case, these are all from my trip to &lt;a href=&quot;https://idc.acm.org/2023/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;IDC’23&lt;/a&gt; from wandering around the city after the presentations.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/photos/chicago_002.png&quot; /&gt;
    &lt;figcaption&gt;Coming from Lancaster, where there aren&#39;t many tall buildings, what struck me in particular was the sheer number of floors on every building.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;One of the things that I found a bit disconcerting was how often you’ll be at the foot of very tall buildings all around you, which has a very similar feeling as to being at the bottom of a deep valley. I’m a bit more used to open spaces, so the overall effect was a bit claustrophobic, something which I’m not normally afflicted with.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/photos/chicago_004.png&quot; /&gt;
    &lt;figcaption&gt;The classic panorama shot, showing the buildings river and boats. Taken from the railings on the river just outside the Apple store at the riverside.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/photos/chicago_003.png&quot; /&gt;
    &lt;figcaption&gt;Another classic shot of the overhead metro.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/photos/chicago_005.png&quot; /&gt;
    &lt;figcaption&gt;Lots of boat trips on the river in Chicago. The conference organisers actually organised one that I could have gone on, but the costs were a bit prohibitive, unfortunately.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/photos/chicago_006.png&quot; /&gt;
    &lt;figcaption&gt;In the plazas near the riverside there are quite a few statues. Unfortunately I didn&#39;t have time to read the plaque about this one, only having enough time to snap a photo or two and dash off.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;We wandered out of the city a little midway through the trip, going to one of the restaurants in an area known for amazing Mexican food (it was!) but it also exposed us to a little of the behind the scenes.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/photos/chicago_001.png&quot; /&gt;
    &lt;figcaption&gt;A little behind the scenes; an alleyway stretching off into the distance&lt;/figcaption&gt;
&lt;/figure&gt;</content
    >
  </entry>
  <entry>
    <title>“Manjaro Linux on the Yoga Book”</title>
    <link href="https://johnvidler.co.uk/blog/manjaro-linux-on-the-yoga-book/" />
    <updated>2023-06-08T00:00:00Z</updated>
    <id>https://johnvidler.co.uk/blog/manjaro-linux-on-the-yoga-book/</id>
    <content
      xml:lang=""
      type="html"
      >&lt;p&gt;It works (mostly) out of the box now!&lt;/p&gt;
&lt;p&gt;I unfortunately managed to update the pure Arch Linux kernel on the laptop right in the middle of an update that broke support for the chipset that it used; perfectly timed to mean it fails to boot, so was generally unrecoverable.&lt;/p&gt;
&lt;p&gt;Thankfully, I had only installed Linux on the uSD card at this point, so I could reboot into Windows if I had needed a working machine, and it had all my driver and configuration tweaks saved too.&lt;/p&gt;
&lt;p&gt;Experimentally, I had another go with Manjaro Linux with the Gnome/Wayland front end - I had tried this previously, but without the machine booting at all; so you can imagine my surprise when the whole system fired up all the way into the graphical interface.&lt;/p&gt;
&lt;p&gt;Everything that had worked before on Arch, including some surprises with auto screen rotation working out of the box too. Apparently Manjaro include &lt;code&gt;iio-proxy&lt;/code&gt; by default, surfacing almost all the sensors properly so Gnome could use them.&lt;br /&gt;
Naturally an exception was the keyboard, which only came up as a giant touchpad, as was the case for Arch as well, but I hardly expected that it would just work, as its quite the exotic bit of kit; and unfortunately the cameras (front and rear) and the sound card still don’t work, and still come up as a &lt;code&gt;dummy output&lt;/code&gt; and &lt;code&gt;dummy input&lt;/code&gt; on PulseAudio.&lt;/p&gt;
&lt;p&gt;This is great progress, however! It means I don’t need to work to bring a system up from a bare frame buffer state, and can start with most of my work done for me. Being Arch-based, the software I wrote for the keyboard worked out of the box too, so in the space of a couple of hours, I went from a completely dead machine to the same state that I reached before, except with a stable, normal kernel, rather than the mainline one I had to use for Arch.&lt;/p&gt;
</content
    >
  </entry>
  <entry>
    <title>Speech Development (Part 2)</title>
    <link href="https://johnvidler.co.uk/blog/speech-development-part-2/" />
    <updated>2023-06-01T00:00:00Z</updated>
    <id>https://johnvidler.co.uk/blog/speech-development-part-2/</id>
    <content
      xml:lang=""
      type="html"
      >&lt;p&gt;&lt;em&gt;This is a follow up to a &lt;a href=&quot;https://johnvidler.co.uk/blog/speech-development/&quot;&gt;previous article&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;So! It wasn’t me!&lt;/p&gt;
&lt;p&gt;I probably shouldn’t be &lt;em&gt;happy&lt;/em&gt; about this, but knowing that by teaching my daughter sign language I haven’t actually set her back on normal speech development is a significant weight off my shoulders.&lt;/p&gt;
&lt;p&gt;Instead, through some more testing with the fantastic folks at the child hearing clinic near here, we’ve established that she’s hearing everything about &lt;em&gt;2-3 times more quiet&lt;/em&gt; than normal, and that the problem seems to be continued ‘glue ear’ in her middle ear. When she was tested with a bone conduction speaker (and thus, one that avoids exciting the middle ear, but shortcuts directly via the bones in her head) it turned out that her hearing was totally normal, just nothing was getting through because of a middle ear blockage.&lt;/p&gt;
&lt;p&gt;So this leads on to ‘what next?’ for this particular saga; naturally I don’t want her to slowly get behind with speech development as right now she’s propping herself up with the rest of her age group through just being a smart cookie, but that won’t last forever - but the only options right now are either (minor) surgery or having a hearing aid (amplification type, no surgery).&lt;/p&gt;
&lt;p&gt;The NICE&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://johnvidler.co.uk/blog/speech-development-part-2/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; guidelines for the type of surgery that would be required now stipulate that the operation should only normally be done twice over the course of an individuals lifetime, to minimise the scar tissue involved becoming more of a problem, and with my daughter being quite small still (she’s only three!) there’s a good chance that the operation will need to be repeated at a later stage to re-apply the fix pretty soon after the first one fails. So instead of surgery, we’re going down the hearing aid route.&lt;/p&gt;
&lt;p&gt;As a computer scientist this is &lt;em&gt;deeply interesting&lt;/em&gt; to me as well; the miniaturisation of these devices has been fantastic of late, what with all the battery technology advances, but as a resident of the UK, I do now need to arrange for these to be sorted for her through… &lt;strong&gt;The NHS&lt;/strong&gt;&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://johnvidler.co.uk/blog/speech-development-part-2/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;For all its facets, good and bad, the NHS has generally done me and my family pretty well so far; but this is a whole new game with multiple disconnected departments talking to one another via snail mail right in the middle of the largest industrial action seen in recent times&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://johnvidler.co.uk/blog/speech-development-part-2/#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt;. I have all the sympathy for the plight of junior doctors but at the same time I’m not relishing the prospect of navigating the complexities of the NHS.&lt;/p&gt;
&lt;p&gt;Wish us luck!&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://www.nice.org.uk/guidance&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;The National Institute for Health and Care Excellence (NICE) guidelines&lt;/a&gt; &lt;a href=&quot;https://johnvidler.co.uk/blog/speech-development-part-2/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://www.nhs.uk/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;The National Health Service (NHS)&lt;/a&gt; &lt;a href=&quot;https://johnvidler.co.uk/blog/speech-development-part-2/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://www.bbc.co.uk/news/health-65673576&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;“Junior doctors in England to strike for three days in June” - BBC News&lt;/a&gt; &lt;a href=&quot;https://johnvidler.co.uk/blog/speech-development-part-2/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content
    >
  </entry>
  <entry>
    <title>The jac:stack - An Addon for the Micro:bit</title>
    <link href="https://johnvidler.co.uk/blog/the-jacstack-an-addon-for-the-microbit/" />
    <updated>2023-05-30T00:00:00Z</updated>
    <id>https://johnvidler.co.uk/blog/the-jacstack-an-addon-for-the-microbit/</id>
    <content
      xml:lang=""
      type="html"
      >&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/hardware/jacstack-design-whiteboard.png&quot; /&gt;
    &lt;figcaption&gt;The original whiteboard design for the jac:stack. Ultimately I dropped the left-hand Jacdac connector due to space concerns, but the overall design made it all the way to production.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;This is the second iteration of an idea to present GPS support to the Micro:bit, but rather than &lt;a href=&quot;https://johnvidler.co.uk/blog/the-microbit-gps-logger-prototype/&quot;&gt;the previous version&lt;/a&gt; which was more of a dedicated GPS logger board, this one presents the much more flexible Jacdac interface to two ports for screw terminals, or one wire-to-board connection on the right.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/hardware/jacstack-gps.png&quot; /&gt;
    &lt;figcaption&gt;The passthrough module in all its glory - Note that although the GPS _is_ connected to I2C, the firmware on the Adafruit modules makes no use of I2C, and in fact interferes with the normal operation of other I2C peripherals, necessitating me cutting the SDA line to the GPS module&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;jacdac-support&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/the-jacstack-an-addon-for-the-microbit/#jacdac-support&quot;&gt;Jacdac Support&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Jacdac is both an electrical and protocol specification for connecting devices to sensors with as low friction as possible. This is achieved by way of a 3-pin interface (ground is duplicated to make a 4-standoff variant for bolted-on modules) that can be driven with a slightly modified UART in half-duplex mode, and a software stack able to automatically identify connected devices and present a common interface up to higher-level code. The upshot of this complexity is a kind of microcontroller USB.&lt;/p&gt;
&lt;p&gt;Jacdac is developed by Microsoft Research, and the pages for which can be found at &lt;a href=&quot;https://microsoft.github.io/jacdac-docs/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;the project website&lt;/a&gt; over on &lt;a href=&quot;http://github.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;github.io&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I elected to support this protocol here as it opens up a wide range of sensors already developed, and vastly increases the flexibility of the Micro:bit as a sensor platform.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/hardware/jacstack-jacdac-gps.png&quot; /&gt;
    &lt;figcaption&gt;My development module, including the lovely airwire link between the UART transmit pin and P0, as I accidentally destroyed the solder jumper on the back of the board. Also featuring a Kittenbot Magnet Sensor board on the right-hand Jacdac port&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;adafruit-ultimate-gps-support&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/the-jacstack-an-addon-for-the-microbit/#adafruit-ultimate-gps-support&quot;&gt;Adafruit “Ultimate GPS” Support&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Having had no luck whatsoever with GPS modules on the previous design, I chose to pick as close to a ‘fully integrated’ module as I could, and costs therein be damned. Consequently, this board uses the &lt;a href=&quot;https://www.adafruit.com/product/790&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Adafruit Ultimate GPS Module&lt;/a&gt;; a reasonably small, but very capable module that should just work&lt;sup&gt;TM&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;The module boasts quite the set of features (list taken from the Adafruit product page):&lt;/p&gt;
&lt;ul class=&quot;list&quot;&gt;
&lt;li&gt;-165 dBm sensitivity, 10 Hz updates, 66 channels&lt;/li&gt;
&lt;li&gt;Ultra low power usage: 20mA current draw while tracking&lt;/li&gt;
&lt;li&gt;3.3V operation,&lt;/li&gt;
&lt;li&gt;RTC battery-compatible&lt;/li&gt;
&lt;li&gt;Built-in datalogging&lt;/li&gt;
&lt;li&gt;PPS output on fix&lt;/li&gt;
&lt;li&gt;We have received reports that it works up to ~32Km altitude (the GPS theoretically does not have a limit until 40Km)&lt;/li&gt;
&lt;li&gt;Internal patch antenna + connection for optional external active antenna&lt;/li&gt;
&lt;li&gt;Fix status output&lt;/li&gt;
&lt;li&gt;Ultra small size: only 16mm x 16mm x 5mm and 4 grams&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But what was most interesting to me in this case was the inclusion of both UART and I2C peripheral pins; and as the Clip:bit input board exclusively uses I2C to not content with any other peripherals, perhaps I could wrangle this module into working without using any more pins on the Micro:bit, freeing them for other, more fun stuff.&lt;/p&gt;
&lt;p&gt;Unfortunately, the default firmware seems to have no way to set the module to send data over I2C, so instead I had to fall back to using P0 for serial data. Thankfully for the work I’m doing with this module we aren’t using anything connected to P0, so this proved to not be a major issue.&lt;/p&gt;
&lt;h3 id=&quot;nmea-data&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/the-jacstack-an-addon-for-the-microbit/#nmea-data&quot;&gt;NMEA Data&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;With the hardware completed, I also needed to write software for the Micro:bit and &lt;a href=&quot;https://makecode.microbit.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Makecode&lt;/a&gt; which would present the positional and time data to the user without having to deal with raw &lt;a href=&quot;https://en.wikipedia.org/wiki/NMEA_0183&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;NMEA strings&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To this end, I produced a set of blocks for Makecode which let users simply pull in a &lt;code&gt;latitude&lt;/code&gt; or &lt;code&gt;longitude&lt;/code&gt; block to get their location.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/hardware/ultimate-gps-pinout.png&quot; /&gt;
    &lt;figcaption&gt;Taken from the module datasheet; note the multiplexed I2C pins as well as the usual UART pins&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;gps-logging&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/the-jacstack-an-addon-for-the-microbit/#gps-logging&quot;&gt;GPS Logging&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Throwing this new extension in with the Micro:bit v2 Data Logger extension provides all the tools to do some basic GPS path logging, with the device periodically sampling its location and writing that to flash (along with any relevant sensor data). Further augmenting the functionality with the addition of the Clip:bit gives a powerful survey platorm that can both log&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/JohnVidler/pxt-jac-stack&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/JohnVidler/pxt-jac-stack&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;https://github.com/JohnVidler/pxt-mock-gps&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/JohnVidler/pxt-mock-gps&lt;/a&gt;&lt;/p&gt;
</content
    >
  </entry>
  <entry>
    <title>The clip:bit - An Addon for the Micro:bit</title>
    <link href="https://johnvidler.co.uk/blog/the-clipbit-an-addon-for-the-microbit/" />
    <updated>2023-05-20T00:00:00Z</updated>
    <id>https://johnvidler.co.uk/blog/the-clipbit-an-addon-for-the-microbit/</id>
    <content
      xml:lang=""
      type="html"
      >&lt;blockquote&gt;
&lt;p&gt;I’m still writing this article, expect missing content! -John&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;This work was published at IDC’23!&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://johnvidler.co.uk/blog/the-clipbit-an-addon-for-the-microbit/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;&lt;br /&gt;
See the paper and poster here:&lt;/p&gt;
&lt;ul class=&quot;list&quot;&gt;
&lt;li&gt;&lt;em&gt;Supporting fieldwork for primary education with computing – micro:bit, clip:bit and game controllers.&lt;/em&gt;&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://johnvidler.co.uk/blog/the-clipbit-an-addon-for-the-microbit/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Introducing Classroom Cloudlet: a mobile, tangible, and transparent approach to Internet of Things education.&lt;/em&gt;&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://johnvidler.co.uk/blog/the-clipbit-an-addon-for-the-microbit/#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Dear reader, please be kind to me on this one. For whatever reason, many of the components on this design have been particularly impacted by the ongoing (mid-2023) chip/parts shortage, and it caused me to have to replace &lt;em&gt;rather a lot&lt;/em&gt; of the ones I wanted to use with nearly-alike alternatives, which does rather leave the board in a state which might look a bit strange to those of you in the design game.&lt;/p&gt;
&lt;p&gt;…&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/hardware/clipbit-purple-incomplete.png&quot; /&gt;
    &lt;figcaption&gt;A purple clip:bit, in all its slightly incomplete glory. The through-hole parts were manually added later, to speed up the manufacturing at JLCPCB.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/hardware/clipbit-red.png&quot; /&gt;
    &lt;figcaption&gt;A complete clip:bit in (nearly) Lancaster University Red. Don&#39;t come after me marketing team... I only had the base FR4 colours to choose from!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;circle-intersection-is-a-pain!&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/the-clipbit-an-addon-for-the-microbit/#circle-intersection-is-a-pain!&quot;&gt;Circle Intersection is a Pain!&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This wasn’t very painful, but getting a contiguous line along a series of arcs in KiCAD takes a certain amount of finesse; an amount that I did not have at the start of this work, and resulted in some messing around to get the circle paths to line up in such a way that I could make KiCAD snap the arc segments together for a smooth cloud shape.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/hardware/clipbit-circles-logo.png&quot; /&gt;
    &lt;figcaption&gt;The clip:bit logo, showing all the construction circles I used to get the alignment &lt;i&gt;just so&lt;/i&gt;.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The trick, should anyone want to replicate this in their own work; is to enable grid snapping for your circle templates on a &lt;code&gt;user#&lt;/code&gt; layer, then &lt;em&gt;turn all snapping off&lt;/em&gt; to trace over the templates where you actually want your silkscreen/edge cut lines to be, otherwise KiCAD will do &lt;em&gt;everything&lt;/em&gt; in its power to try and snap you to stuff you don’t want. The grid, pads, other lines, the center mark, horizontal/vertical alignment points… resulting in not-quite-perfectly-joined paths that will make the DRC hate you.&lt;/p&gt;
&lt;h2 id=&quot;better-routing-decisions&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/the-clipbit-an-addon-for-the-microbit/#better-routing-decisions&quot;&gt;Better Routing Decisions&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are several places on the board where rushed decisions caused more trouble than they should - here for example I should have rotated the driver chip for the 7-segment displays 90 degrees left OR right, then routed out the side of the chip rather than resorting to the slightly ugly traces under the chip.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/hardware/clipbit-display-traces.png&quot; /&gt;
    &lt;figcaption&gt;The left-hand display traces on the clip:bit v3. This is a dumb way of routing these!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The rotation would have caused the LEDs mappings for each segment to change, but as these would be defined in software anyway, this is a non-problem and should have been corrected at the design stages.&lt;/p&gt;
&lt;p&gt;Oh well… it &lt;em&gt;does&lt;/em&gt; work, and in some senses protects the traces from damage by moving them closer to the center of the board, rather than having to be right at the left-hand edge.&lt;/p&gt;
&lt;p&gt;I don’t miss placing all those resistors though! Yeesh!&lt;/p&gt;
&lt;h3 id=&quot;the-power-switch&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/the-clipbit-an-addon-for-the-microbit/#the-power-switch&quot;&gt;The Power Switch&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Another issue was with the side-actuated power switch, again added at the end of the design process, and I was forced to pick a part that I could actually find stock of (at the time of writing, the chip/component shortage is still a &lt;em&gt;very real&lt;/em&gt; annoyance). Unfortunately a combination of slightly too thin mounting pads, and poor mechanical construction of the switches results in many of them being damaged by users.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/hardware/clipbit-power-switch.png&quot; /&gt;
    &lt;figcaption&gt;Added right at the end of the design process, this switch (SW13) proved totally inadequate&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;One option that I should have perhaps explored further is to toggle the power through the insersion/removal of the micro:bit itself - there are additional traces for power, so routing &lt;em&gt;through&lt;/em&gt; a set of pads on the edge connector is possible, but in this design would have resulted in some long power traces running up the back-side of the board to support this. At the time, I thought that this was too risky as long traces on a surface that could be placed on rock, or other abrasive surfaces would likely just be a recipie for disaster, but for v4 I’m absolutely moving to that design to remove the switch!&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pxt-clip-bit&lt;/code&gt;&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://johnvidler.co.uk/blog/the-clipbit-an-addon-for-the-microbit/#fn4&quot; id=&quot;fnref4&quot;&gt;[4]&lt;/a&gt;&lt;/sup&gt;&lt;br /&gt;
&lt;code&gt;pxt-paged-data-log&lt;/code&gt;&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://johnvidler.co.uk/blog/the-clipbit-an-addon-for-the-microbit/#fn5&quot; id=&quot;fnref5&quot;&gt;[5]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;ACM Interaction Design and Children (IDC) Conference; 2023 - &lt;a href=&quot;https://idc.acm.org/2023/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://idc.acm.org/2023/&lt;/a&gt; &lt;a href=&quot;https://johnvidler.co.uk/blog/the-clipbit-an-addon-for-the-microbit/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Elizabeth Edwards, John Edward Vidler, Lorraine Underwood, Elisa Rubegni, and Joe Finney. 2023. Supporting fieldwork for primary education with computing – micro:bit, clip:bit and game controllers. In Proceedings of the 22nd Annual ACM Interaction Design and Children Conference (IDC ’23). Association for Computing Machinery, New York, NY, USA, 553–557. &lt;a href=&quot;https://doi.org/10.1145/3585088.3593897&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://doi.org/10.1145/3585088.3593897&lt;/a&gt; &lt;a href=&quot;https://johnvidler.co.uk/blog/the-clipbit-an-addon-for-the-microbit/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Lorraine Underwood, Elizabeth Edwards, John Edward Vidler, Elisa Rubegni, and Joe Finney. 2023. Introducing Classroom Cloudlet: a mobile, tangible, and transparent approach to Internet of Things education. In Proceedings of the 22nd Annual ACM Interaction Design and Children Conference (IDC ’23). Association for Computing Machinery, New York, NY, USA, 740–744. &lt;a href=&quot;https://doi.org/10.1145/3585088.3594487&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://doi.org/10.1145/3585088.3594487&lt;/a&gt; &lt;a href=&quot;https://johnvidler.co.uk/blog/the-clipbit-an-addon-for-the-microbit/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn4&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/johnvidler/pxt-clip-bit/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;The Clip:bit extension for MakeCode&lt;/a&gt; &lt;a href=&quot;https://johnvidler.co.uk/blog/the-clipbit-an-addon-for-the-microbit/#fnref4&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn5&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/JohnVidler/pxt-paged-data-log&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;The Paged Data extension for MakeCode&lt;/a&gt; &lt;a href=&quot;https://johnvidler.co.uk/blog/the-clipbit-an-addon-for-the-microbit/#fnref5&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content
    >
  </entry>
  <entry>
    <title>The Micro:bit - GPS Logger Prototype</title>
    <link href="https://johnvidler.co.uk/blog/the-microbit-gps-logger-prototype/" />
    <updated>2023-05-10T00:00:00Z</updated>
    <id>https://johnvidler.co.uk/blog/the-microbit-gps-logger-prototype/</id>
    <content
      xml:lang=""
      type="html"
      >&lt;p&gt;This module is rather unimaginably named the ‘Micro:bit GPS Logger Prototype’ as it never really worked well enough to warrant a proper, snappy name.&lt;br /&gt;
Unfortunately despite the module I selected communicating beautifully over i2c pretty much immediately, I failed to correctly account for the ground plane requirements for the GPS antenna to function, resulting in a great looking, but ultimately functionless module.&lt;/p&gt;
&lt;h3 id=&quot;an-auxillary-power-connector-jst&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/the-microbit-gps-logger-prototype/#an-auxillary-power-connector-jst&quot;&gt;An auxillary power connector (JST)&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Its a power connector!&lt;/p&gt;
&lt;p&gt;No, really, its not really all that interesting for this one; I included this to present battery backup power to the GPS module, even when the Micro:bit is in deep sleep or power-off modes, keeping the last set of satellite fixes in memory until they’re needed again.&lt;/p&gt;
&lt;p&gt;I threw on some protection diodes as well, such that powering the board through the Micro:bit USB connector, the Micro:bit JST battery connector and using this connector, even &lt;em&gt;all at once&lt;/em&gt; should be fine, without any power supply trying to back-feed power into a battery with all the potentially firey consequences that would have. The diodes introduce a little bit of a voltage drop, but as this was intended for something like a set of AA cells (or bigger) they would have the voltage overhead to not matter.&lt;/p&gt;
&lt;h3 id=&quot;a-push-push-type-micro-sd-card-slot&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/the-microbit-gps-logger-prototype/#a-push-push-type-micro-sd-card-slot&quot;&gt;A ‘push-push’ type micro-SD card slot.&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Micro-SD cards have a really handy SPI mode, and can be hooked directly into any 3v3 microcontroller that can support SPI. You still need some software capable of reading the filesystem on the card (or just treat it all as a giant EMMC and deal with such nonsense as ‘reading’ the data on a computer later), but electrically this is extremely simple.&lt;/p&gt;
&lt;p&gt;The connector itself is a nice push-push type with a little bi-stable spring to eject the card. This allows the user to just press the card into the slot until a &lt;em&gt;very&lt;/em&gt; satisfying click is heard, then simply press it again to have it pop pleasingly out far enough to comfortably grab. This plus a little milling out around the edge of the PCB to make grabbing the card easier finishes this off.&lt;/p&gt;
&lt;p&gt;Unfortunately, as this function wasn’t the main focus of the work at the time, the software to drive the card remains incomplete, although there is every chance I’ll revisit this at a later time when I need larger long-term storage on a micro:bit… perhaps for long-term datalogging in hard-to-access places; such as being deployed in a forest for environmental monitoring duties.&lt;/p&gt;
&lt;h3 id=&quot;a-cam-m8c-0-gps-module&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/the-microbit-gps-logger-prototype/#a-cam-m8c-0-gps-module&quot;&gt;A CAM-M8C-0 GPS module&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In theory this should have been a great little module - its expensive, but is very capable, and can communicate over i2c, so no pin sacrifice would be required to use the module - we can just simply pass the i2c connections through from one Micro:bit connector to the other, and tap into them for communication to the GPS module. The Micro:bit even has the requisite pullups for i2c already on-board, so this board could skip the two extra resistors normally required.&lt;/p&gt;
&lt;p&gt;Unfortunately, it would transpire the this particular module is particularly sensitive to the shape and placement of the module relative to the PCB groundplane.&lt;br /&gt;
I had accounted for the required cutout on the underside where the module is soldered to the PCB, but to function &lt;em&gt;at all&lt;/em&gt; it seems that this little GPS needs to effectively use some of its carrier PCB groundplane as part of its own antenna. Not knowing this (As I’ve not used this particular module before, and missed it on the datasheet) I didn’t leave enough free space around the module for the antenna to function, so while we get some perfect NMEA strings back from it - the total number of satellite fixes never goes above zero, even in otherwise ideal conditions.&lt;/p&gt;
&lt;p&gt;In hindsight, perhaps I should have also broken out the antenna trace to a u.FL connection, so that an external antenna could be used, but that would require planning! Perhaps someday I’ll revisit this module in this design, and do this, but for now its relegated to the archive while work progresses in other directions.&lt;/p&gt;
&lt;h3 id=&quot;software&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/the-microbit-gps-logger-prototype/#software&quot;&gt;Software&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As part of developing this board, I also quickly threw together this little MakeCode&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://johnvidler.co.uk/blog/the-microbit-gps-logger-prototype/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; extension, &lt;code&gt;pxt-mock-gps&lt;/code&gt;&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://johnvidler.co.uk/blog/the-microbit-gps-logger-prototype/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;, which uses a preloaded set of coordinates and a timer to passively ‘wander around’ the Lancaster University campus over time, allowing my colleagues to experiment with code that used location data in their code sketches.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://makecode.microbit.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://makecode.microbit.org/&lt;/a&gt; &lt;a href=&quot;https://johnvidler.co.uk/blog/the-microbit-gps-logger-prototype/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/JohnVidler/pxt-mock-gps&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/JohnVidler/pxt-mock-gps&lt;/a&gt; &lt;a href=&quot;https://johnvidler.co.uk/blog/the-microbit-gps-logger-prototype/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content
    >
  </entry>
  <entry>
    <title>Speech Development</title>
    <link href="https://johnvidler.co.uk/blog/speech-development/" />
    <updated>2023-03-03T00:00:00Z</updated>
    <id>https://johnvidler.co.uk/blog/speech-development/</id>
    <content
      xml:lang=""
      type="html"
      >&lt;p&gt;I recently found out from the preschool that my daughter isn’t keeping up with the other kids with her speech development.&lt;br /&gt;
This came as quite a surprise, as although her speech is a bit garbled, due in part to being a kid, but also as she currently has a case of ‘glue ear’ so she’s not hearing things quite correctly; she is normally quite a chatterbox at home, and her talking away has been noted by both sets of grandparents.&lt;/p&gt;
&lt;p&gt;The preshcool folks have apparently seen her talking to other kids, but she doesn’t chat with them.&lt;/p&gt;
&lt;p&gt;So the options, as far as I can see here are:&lt;/p&gt;
&lt;ol class=&quot;list&quot;&gt;
&lt;li&gt;With all the other kids at preschool, she’s just not as clear as a quiet home environment.&lt;/li&gt;
&lt;li&gt;She’s a quiet kid at ‘school’, so simply doesn’t &lt;em&gt;want&lt;/em&gt; to talk to everyone&lt;/li&gt;
&lt;li&gt;Something else, developmental or hearing related.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;…or even worse: Its my/our fault …somehow.&lt;/p&gt;
&lt;p&gt;I’ve been learning British Sign Language (BSL) since she was very small, as we had been using Makaton sign with her since before she could speak at all.&lt;br /&gt;
Part of me wonders if this is actually slowing her down now.&lt;br /&gt;
She signs very well for a 2.5 year old, as far as I can tell as a learner myself - she keeps up with me at full speed at least, and responds in kind, but is that just that she’s focussing on this because its what we do rather than her speech itself?&lt;/p&gt;
&lt;p&gt;Have I slowed her speech development?&lt;/p&gt;
&lt;p&gt;Its probably nothing.&lt;br /&gt;
&lt;em&gt;Probably&lt;/em&gt;.&lt;br /&gt;
But I have to assume the worst because anything else might be a disservice to her later down the line; so now we’re actively encouraging her to speak up, speak clearly and to talk with her ‘teachers’ at the preschool.&lt;/p&gt;
&lt;p&gt;They’re working with her too, doing 1:1 sessions, reading with her, and so forth to see how she responds.&lt;/p&gt;
&lt;p&gt;But for now; I think I’m going to put this into the ‘deep dark fears’ pile.&lt;/p&gt;
&lt;p&gt;She’s my first (and currently only) kiddo, so all of this is entirely new to me, so everything is doubly terrifying whenever anything going wrong.&lt;br /&gt;
I’d love to be the kind of chilled-out parent that can just float through doing all the right things at all the right times, but I’m also nearly convinced that they don’t actually exist.&lt;/p&gt;
&lt;p&gt;Finally a word of advice for new parents - don’t take the books to heart; I’m entirely convinced that the people who write those things are essentially outliers with specific problems, rather than the average case.&lt;br /&gt;
That isn’t to say that the books are useless, just that you need to take everything they say with a pinch of fiction; every kid is different, so the books are going to only be of passing relevance.&lt;br /&gt;
Maybe some parts map &lt;em&gt;perfectly&lt;/em&gt; onto what you’re seeing with your kids, but that doesn’t mean &lt;em&gt;everything&lt;/em&gt; they say will be correct.&lt;/p&gt;
</content
    >
  </entry>
  <entry>
    <title>Arch Linux on the Yoga Book</title>
    <link href="https://johnvidler.co.uk/blog/arch-linux-on-the-yoga-book/" />
    <updated>2023-01-02T00:00:00Z</updated>
    <id>https://johnvidler.co.uk/blog/arch-linux-on-the-yoga-book/</id>
    <content
      xml:lang=""
      type="html"
      >&lt;p&gt;I have a Yoga Book - the only laptop that I’ve actively wanted at launch - and with its release now in the dim and distant past of 2016 its really showing the age of its hardware, so I’ve decided after some deliberation to attempt to get a working Linux stack running on it.&lt;/p&gt;
&lt;p&gt;There were two versions of the laptop at launch, one running Windows 10 and the other running Android, and while they may appear similer externally, they are very different internally.&lt;br /&gt;
Mine is the Windows 10 edition, so runs a &lt;em&gt;fairly&lt;/em&gt; normal EFI boot configuration and can run USB ISOs, and has the following specification:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Operating System&lt;/td&gt;
&lt;td&gt;Windows 10 Anniversary Edition&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CPU&lt;/td&gt;
&lt;td&gt;1.44GHz Intel Atom x5-Z8550 (quad-core, 2MB cache, up to 2.4GHz with Turbo Boost)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Graphics&lt;/td&gt;
&lt;td&gt;Intel HD Graphics 400&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RAM&lt;/td&gt;
&lt;td&gt;4GB (LPDDR3)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Screen&lt;/td&gt;
&lt;td&gt;10.1-inch FHD (1,920 x 1,200 resolution), IPS touchscreen&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;64GB flash storage (expandable by up to 128GB via microSD)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ports&lt;/td&gt;
&lt;td&gt;microUSB, microHDMI, 3.5mm audio jack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Battery&lt;/td&gt;
&lt;td&gt;8,500mAh&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Connectivity&lt;/td&gt;
&lt;td&gt;802.11ac Wi-Fi (2.4 &amp;amp; 5GHz), optional 4G radio, Bluetooth 4.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Camera&lt;/td&gt;
&lt;td&gt;2MP front-facing webcam with fixed focus; 8MP rear camera with auto-focus&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Weight&lt;/td&gt;
&lt;td&gt;1.52 pounds (690g)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Size&lt;/td&gt;
&lt;td&gt;10.1 x 6.72 x 0.38-inches (256.6 x 170.8 x 0.96mm; W x D x H)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Its &lt;em&gt;ludicrously&lt;/em&gt; slim as compared to laptops of the time, and performed well enough that I used to present my lectures directly from the thing, plugging in via a micro-HDMI port to connect up to a projector.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/linux-laptop/yoga-book-thin.png&quot; /&gt;
    &lt;figcaption&gt;Its just so thin! Its thinner than its own pen! Its barely tall enough to have a 3.5mm audio jack; but also &#39;Boo&#39; at Lenovo for not making the version I have use USB-C (Image credit: Lenovo)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;It has the usual touch screen input, which is handy for when you’re using it in ‘tablet mode’ with the keyboard folded all the way back, but the truly odd thing about the hardware is the keyboard/touchpad/digitizer combination input area.&lt;br /&gt;
This is placed where the keyboard would be on a traditional laptop, but instead is a full-size touch panel, with electroluminescent&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://johnvidler.co.uk/blog/arch-linux-on-the-yoga-book/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; (EL) lines and glyphs to indicate the virtual key areas.&lt;br /&gt;
It also has a mode switch (also a sort of touch keypad) which toggles the EL panel off, and converts the entire area to a Wacom&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://johnvidler.co.uk/blog/arch-linux-on-the-yoga-book/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; style digitizer, compatible with any electromagnetic resonance (EMR)&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://johnvidler.co.uk/blog/arch-linux-on-the-yoga-book/#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt; pen as an input.&lt;/p&gt;
&lt;p&gt;However, provided that I can get this machine to boot, I should be OK on the hardware otherwise, as it uses fairly common components for everyhing except the input layer.&lt;/p&gt;
&lt;h3 id=&quot;booting!&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/arch-linux-on-the-yoga-book/#booting!&quot;&gt;Booting!&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;So, armed with a Manjaro Linux&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://johnvidler.co.uk/blog/arch-linux-on-the-yoga-book/#fn4&quot; id=&quot;fnref4&quot;&gt;[4]&lt;/a&gt;&lt;/sup&gt; bootable USB I attempted to get past the EFI loader aaand… nothing. Zip. Zero.&lt;br /&gt;
Just a black screen, not even the legendary blinking cursor of death for GRUB-based boot systems.&lt;/p&gt;
&lt;p&gt;Undeterred, I threw Alpine Linux[^5] at it, aaaand nothing.&lt;/p&gt;
&lt;p&gt;At this point I was beginning to think that I’d need some kind of magic to get into a bootloader, but then I tried Puppy Linux[^6], knowing that it is famously light on resources and runs on a wide variety of older hardware just fine; and success! Kinda!&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/linux-laptop/yoga-book-puppy-linux.jpg&quot; /&gt;
    &lt;figcaption&gt;Err, Puppy Linux...? Are you OK?&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Well, its &lt;em&gt;running&lt;/em&gt; at least!&lt;/p&gt;
&lt;p&gt;I could get past the GRUB stage, and get the kernel loaded. Early boot messages seemed to be scrolling, and then it dropped to this mess.&lt;br /&gt;
So this is promising, as it shows that Linux in some variation is capable of booting into some form of runtime.&lt;/p&gt;
&lt;p&gt;Puppy linux has a ‘safe mode’ terminal-only boot mode, and I figured, why not give it a go, as I could read the GRUB prompt just fine, so I can toy with linux boot args and get to a terminal-only framebuffer maybe?&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/linux-laptop/yoga-book-puppy-terminal.jpg&quot; /&gt;
    &lt;figcaption&gt;Puppy Linux... you might have some video issues there...&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;From prodding a USB attached keyboard (actually a USB-OTG adapter to a USB hub with built-in ethernet, because this thing has &lt;em&gt;no ports whatsoever!&lt;/em&gt;) I could see that I was getting characters on a terminal, and the right kind of output &lt;em&gt;vaguely&lt;/em&gt; presented itself on the screen.&lt;br /&gt;
Typing &lt;code&gt;ping 8.8.8.8&lt;/code&gt; resulted in the usual 1 line per second return, so I was pretty confident that the system was booted, and running Bash, but the video config was horribly mangled.&lt;/p&gt;
&lt;p&gt;At this point I was pretty disappointed, as I had expected to see something for a bare framebuffer boot, but after some thought I figured it would be worth trying bare Arch Linux (from which Manjaro is based) and slowly bringing components up bit by bit.&lt;/p&gt;
&lt;p&gt;It worked! Arch ran out of the box just fine - and I was presented with the usual install/recovery environment on the live USB, allowing me to finally install a full system onto the micro-SD card I had in the laptop.&lt;br /&gt;
While I had a running system, I took a prod around to see what devices actually came up as, and they’re listed here for the curious:&lt;/p&gt;
&lt;pre class=&quot;language-plaintext&quot;&gt;&lt;code class=&quot;language-plaintext&quot;&gt;[john@yoga-book ~]$ lspci -tv
-[0000:00]-+-00.0  Intel Corporation Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series SoC Transaction Register
           +-02.0  Intel Corporation Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Integrated Graphics Controller
           +-03.0  Intel Corporation Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series Imaging Unit
           +-0a.0  Intel Corporation Device 22d8
           +-0b.0  Intel Corporation Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series Power Management Controller
           +-14.0  Intel Corporation Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series USB xHCI Controller
           +-1a.0  Intel Corporation Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series Trusted Execution Engine
           +-1c.0-[01]----00.0  Broadcom Inc. and subsidiaries BCM4356 802.11ac Wireless Network Adapter
           &#92;-1f.0  Intel Corporation Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series PCU

[john@yoga-book ~]$ lsusb -tv
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/6p, 5000M
    ID 1d6b:0003 Linux Foundation 3.0 root hub
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/7p, 480M
    ID 1d6b:0002 Linux Foundation 2.0 root hub

[john@yoga-book ~]$ hwinfo --short
cpu:                                                            
                       Intel(R) Atom(TM) x5-Z8550  CPU @ 1.44GHz, 2400 MHz
                       Intel(R) Atom(TM) x5-Z8550  CPU @ 1.44GHz, 2400 MHz
                       Intel(R) Atom(TM) x5-Z8550  CPU @ 1.44GHz, 2400 MHz
                       Intel(R) Atom(TM) x5-Z8550  CPU @ 1.44GHz, 2400 MHz
mouse:
  /dev/input/mice      HDP0001:00 2ABB:8102
  /dev/input/mice      Goodix Capacitive TouchScreen
graphics card:
                       Intel Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Integrated Graphics Controller
network:
  wlp1s0               Broadcom BCM4356 802.11ac Wireless Network Adapter
network interface:
  wlp1s0               Ethernet network interface
  lo                   Loopback network interface
disk:
  /dev/mmcblk0         Disk
  /dev/mmcblk0boot0    Disk
  /dev/mmcblk1         Disk
  /dev/mmcblk0boot1    Disk
partition:
  /dev/mmcblk0p1       Partition
  /dev/mmcblk0p2       Partition
  /dev/mmcblk0p3       Partition
  /dev/mmcblk0p4       Partition
  /dev/mmcblk1p1       Partition
  /dev/mmcblk1p2       Partition
usb controller:
                       Intel Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series USB xHCI Controller
bios:
                       BIOS
bridge:
                       Intel Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series PCI Express Port #1
                       Intel Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series PCU
                       Intel Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series SoC Transaction Register
hub:
                       Linux Foundation 2.0 root hub
                       Linux Foundation 3.0 root hub
memory:
                       Main Memory
unknown:
                       FPU
                       DMA controller
                       PIC
                       Keyboard controller
                       Intel Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series Imaging Unit
                       Intel Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series Trusted Execution Engine
                       Intel Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series Power Management Controller
                       Intel Unclassified device
                       Serial controller&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/linux-laptop/yoga-book-arch-install.jpg&quot; /&gt;
    &lt;figcaption&gt;Arch Linux installing to the micro-SD card in the Yoga Book&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/linux-laptop/yoga-book-keyboard-mode.jpg&quot; /&gt;
    &lt;figcaption&gt;The keyboard area all lit up! It changes modes by default, but will not work as a keyboard without further work&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/linux-laptop/yoga-book-arch-xfce4-90.jpg&quot; /&gt;
    &lt;figcaption&gt;XFCE4 seems to want to run rotated 90 degrees...&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/linux-laptop/yoga-book-arch-rotate-fix.jpg&quot; /&gt;
    &lt;figcaption&gt;Forcing the rotation over seems to work, but the rotation sensors aren&#39;t talking to me right now.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;device-status&quot;&gt;&lt;a class=&quot;heading-anchor&quot; href=&quot;https://johnvidler.co.uk/blog/arch-linux-on-the-yoga-book/#device-status&quot;&gt;Device Status&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The following is just a kind of checklist for me to keep track of what is working, and what still needs attention.&lt;/p&gt;
&lt;ul class=&quot;list&quot;&gt;
&lt;li&gt;[x] Boot (EFI)
&lt;ul class=&quot;list&quot;&gt;
&lt;li&gt;[x] From USB&lt;/li&gt;
&lt;li&gt;[x] From uSD&lt;/li&gt;
&lt;li&gt;[ ] From SSD&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;[x] WiFi&lt;/li&gt;
&lt;li&gt;[ ] Bluetooth&lt;/li&gt;
&lt;li&gt;Audio
&lt;ul class=&quot;list&quot;&gt;
&lt;li&gt;[ ] Speakers&lt;/li&gt;
&lt;li&gt;[ ] 3.5mm Jack&lt;/li&gt;
&lt;li&gt;[ ] HDMI Output&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Video
&lt;ul class=&quot;list&quot;&gt;
&lt;li&gt;[x] Terminal shells&lt;/li&gt;
&lt;li&gt;[x] X11
&lt;ul class=&quot;list&quot;&gt;
&lt;li&gt;[x] Screen Rotation&lt;/li&gt;
&lt;li&gt;[ ] Display Brightness&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;[ ] uHDMI Output&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Input
&lt;ul class=&quot;list&quot;&gt;
&lt;li&gt;[ ] Trackpad&lt;/li&gt;
&lt;li&gt;[ ] Keyboard (virtual)&lt;/li&gt;
&lt;li&gt;[x] Touch Screen&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;[x] USB
&lt;ul class=&quot;list&quot;&gt;
&lt;li&gt;[x] USB-OTG&lt;/li&gt;
&lt;li&gt;[x] USB Ethernet&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;EL panel tech link &lt;a href=&quot;https://johnvidler.co.uk/blog/arch-linux-on-the-yoga-book/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;The Wacom homepage &lt;a href=&quot;https://johnvidler.co.uk/blog/arch-linux-on-the-yoga-book/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;EMR tech link &lt;a href=&quot;https://johnvidler.co.uk/blog/arch-linux-on-the-yoga-book/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn4&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Manjaro Linux, based on &lt;a href=&quot;https://archlinux.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Arch Linux&lt;/a&gt; under the hood - &lt;a href=&quot;https://manjaro.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Manjaro&lt;/a&gt; &lt;a href=&quot;https://johnvidler.co.uk/blog/arch-linux-on-the-yoga-book/#fnref4&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content
    >
  </entry>
  <entry>
    <title>Sleep</title>
    <link href="https://johnvidler.co.uk/blog/sleep/" />
    <updated>2022-12-24T00:00:00Z</updated>
    <id>https://johnvidler.co.uk/blog/sleep/</id>
    <content
      xml:lang=""
      type="html"
      >&lt;p&gt;I’ve always struggled with sleep, even from a very early age; my mother will gladly regale anyone who asks that as a toddler, she would leave me to sleep whenever or wherever I fell asleep, as she could never get me down for a nap otherwise.&lt;br /&gt;
Since I’ve discovered that I have some form of frontal lobe brain issue, I’ve put my sleep issues down as part of it and just deal with the battle each night.&lt;/p&gt;
&lt;p&gt;Put simply, I don’t seem to have much of a “being sleepy” phase… I’m either awake, or asleep, with nothing in between.&lt;br /&gt;
I do get &lt;em&gt;tired&lt;/em&gt; but it doesn’t make me want to sleep.&lt;br /&gt;
I couldn’t count the number of times I’ve been jammed awake, completely exhausted but entirely unable to sleep.&lt;/p&gt;
&lt;p&gt;Now I have a daughter.&lt;/p&gt;
&lt;p&gt;Well, I’ve had one for a while really. At the time in writing this she’s about 2.5 years old, and just beginning to sleep on her own, in a separate bed (we did the whole co-sleeping thing to begin with) and getting her to sleep is &lt;em&gt;nightmare&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;She’s definitely a “high energy” child at the best of times, and we both love her energy must of the time, but when it comes to bedtime she’s all over the place, bouncing (sometimes literally) off the walls; getting up in bed, shuffling around, and so on.&lt;br /&gt;
At this point this should sound a bit familiar… And I dearly hope I’m wrong, but…&lt;/p&gt;
&lt;p&gt;… what if she’s just like me?&lt;/p&gt;
&lt;p&gt;It’s a bit of a “deep dark” fear for me.&lt;/p&gt;
&lt;p&gt;I wouldn’t wish my sleep issues on my greatest enemy, let alone my own children and I don’t have any great coping strategies applicable to a toddler.&lt;br /&gt;
I’ve been able to drop off by listening to audio plays, books and the like. I have a set of Goon Show tapes, originally recorded by my father when the episodes were broadcast live on the BBC that used to be played &lt;em&gt;extensively&lt;/em&gt; when I was still living with my parents, and I’ve since transitioned to Audible books and a Bluetooth speaker sleep mask&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://johnvidler.co.uk/blog/sleep/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;; neither of which is likely to be particularly affective with a small child.&lt;/p&gt;
&lt;p&gt;At this point I feel like we’ve tried everything to get her to drift off.&lt;br /&gt;
Warm milk, quiet wind down time, darkened rooms as we get her ready to sleep, a consistent routine, sleeping with teddy, sleeping &lt;em&gt;without&lt;/em&gt; teddy, lying down next to her until she goes, rubbing her back to sooth her… The list could go on endlessly.&lt;br /&gt;
Nothing in particular works, save for pushing through the inevitable tired-baby-tantrum and getting out the other side to exhaustion so she actually sleeps.&lt;/p&gt;
&lt;p&gt;So for now, we struggle through bedtimes through brute force and chaos energy, and each time I hope I can hit on something that works for my daughter, and hope she grows out of it as&lt;br /&gt;
she gets bigger.&lt;/p&gt;
&lt;p&gt;Heck; I’m still going I grow out of it too.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Part of the 500 words challenge I’ve set myself. This doesn’t quite make it, with just 456 words. Oh well.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I highly recommend this to anyone hard-of-sleeping like me, as they block out light &lt;em&gt;and&lt;/em&gt; sound! &lt;a href=&quot;https://johnvidler.co.uk/blog/sleep/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content
    >
  </entry>
  <entry>
    <title>500 Words</title>
    <link href="https://johnvidler.co.uk/blog/500-words/" />
    <updated>2022-12-22T00:00:00Z</updated>
    <id>https://johnvidler.co.uk/blog/500-words/</id>
    <content
      xml:lang=""
      type="html"
      >&lt;p&gt;I’m terrible at writing at length.&lt;/p&gt;
&lt;p&gt;I have a PhD, and as part of this I, like many others before me, had to write up my work in a thesis, and it was &lt;em&gt;absolute hell&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The act of just sitting and writing is something that I’ve found extremely difficult for as long as I can remember.&lt;br /&gt;
In school when essays were handed out as homework every time without fail I would think “Not this time. Not again. I’m going to be better. Start early, and make a good job of this”, but every single time it ended up with me staring at a blank page for hours on end without any tangible idea for how to make it any less blank.&lt;/p&gt;
&lt;p&gt;Late on, I would discover that I have some (or all?) of the traits of ADHD, but back in the ‘bad old days’ ™ we didn’t have these things, and I certainly hadn’t been diagnosed with anything, so I bumbled on through until the latter stages of high school wondering why I found it so extremely difficult to write.&lt;/p&gt;
&lt;p&gt;Still, even armed with a diagnosis I had little in the way of coping strategies to deal with this long into my higher education, and consequently I spent &lt;em&gt;hours&lt;/em&gt; (probably literally days) in the university library just &lt;em&gt;throwing time&lt;/em&gt; at the thesis; bludgeoning it and my wayward brain into submission to get it done.&lt;/p&gt;
&lt;p&gt;Ultimately it got one, and here I am, doctorate in-hand, and with what seems to be more and more of a mild phobia-like reaction to writing longer pieces of work - somewhat of a problem when you work in academia and are required to write at length on complex topics periodically, either to teach or to submit work to conferences and journals.&lt;/p&gt;
&lt;p&gt;So here I am, writing on here instead in an attempt to reset my brain and let it know that yes, you can indeed write at length, and it isn’t anything to be afraid of, and that no papers are going to jump out at you from around the corner or under the bed.&lt;/p&gt;
&lt;p&gt;The plan - such that it is - is to attempt to write about 1 page of standard A4 on some topic or other semi-regularly, for as long as I can manage.&lt;/p&gt;
&lt;p&gt;I’m &lt;em&gt;definitely&lt;/em&gt; going to fail to do this, but that’s not the point - the point is to try.&lt;/p&gt;
&lt;p&gt;So. The rules:&lt;/p&gt;
&lt;ol class=&quot;list&quot;&gt;
&lt;li&gt;Write 500 words per article (minimum)&lt;/li&gt;
&lt;li&gt;Words only count on a ‘blog’ style post&lt;/li&gt;
&lt;li&gt;Words only count if they’re published to this website.&lt;/li&gt;
&lt;li&gt;Formatting marks (as this is written in markdown) and titles, captions, quotes, etc. don’t count.&lt;/li&gt;
&lt;li&gt;Don’t be stressed about missing 500 words or a deadline, just publish.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Lets see how well this works, especially with No. 5…&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Total words: 465&lt;/strong&gt;&lt;/p&gt;
</content
    >
  </entry>
  <entry>
    <title>Micro:bit Disco Demo</title>
    <link href="https://johnvidler.co.uk/blog/microbit-disco-demo/" />
    <updated>2022-06-20T00:00:00Z</updated>
    <id>https://johnvidler.co.uk/blog/microbit-disco-demo/</id>
    <content
      xml:lang=""
      type="html"
      >&lt;p&gt;I’ve thrown together a little demo to show off the micro:bit v2’s microphone functions, mostly to demonstrate the update rate (its very high!).&lt;/p&gt;
&lt;p&gt;Here’s a video of the board listening to my laptop play back some drum and bass (always good for tech demos!) and it updates its lighting to match the beat… mostly!&lt;/p&gt;
&lt;figure&gt;
    &lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/_Z7KoevqShU&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
    &lt;figcaption&gt;My version of the classic Disco Lights demo, running in CODAL on a Micro:bit v2&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Once I remember, I’ll post the code to do this in CODAL/C++ and MakeCode, if folks are interested.&lt;/p&gt;
</content
    >
  </entry>
  <entry>
    <title>Prototype Robot Controller</title>
    <link href="https://johnvidler.co.uk/blog/prototype-robot-controller/" />
    <updated>2022-05-19T00:00:00Z</updated>
    <id>https://johnvidler.co.uk/blog/prototype-robot-controller/</id>
    <content
      xml:lang=""
      type="html"
      >&lt;p&gt;In a fit of buying interesting hardware a while ago, I picked up two of these joystick modules, each has a nice bezel, and two potentiometers on the back for sensing position; but mostly I picked them up becuase they have a really &lt;em&gt;really&lt;/em&gt; nice feel to their movement, and the extended stick length is fantastic.&lt;/p&gt;
&lt;p&gt;The sticks are much more like the length of a professional radio control handset than say, an games controller.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/robot-controller/proto-off-print-bed.jpg&quot; /&gt;
    &lt;figcaption&gt;A back, interior view of the controller, with only one button and switch installed. All are laying on the print bed from a 3d printer&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Naturally, these had to go into a suitable case, and therefore I just kinda… did nothing, while I psyched myself up to actually design something.&lt;/p&gt;
&lt;p&gt;After a little bit of mental back-and-forth, I ended up on this prototype front cover design, which incorporates:&lt;/p&gt;
&lt;ul class=&quot;list&quot;&gt;
&lt;li&gt;Both 2-axis joysticks (Model: JH-D202X-R4)&lt;/li&gt;
&lt;li&gt;6 momentary push buttons&lt;/li&gt;
&lt;li&gt;6 toggle switches&lt;/li&gt;
&lt;li&gt;A 3.2 inch resistive touchscreen HMI from Nextion&lt;/li&gt;
&lt;li&gt;A USB-micro-B connector for programming and/or joystick mode for PC&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/robot-controller/proto-interior.jpg&quot; /&gt;
    &lt;figcaption&gt;A close-up photograph of the interior of the controller, no components wired up&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;My initial plan with all of this was to simply make this a slightly exotic form of HOTAS (Hand On Throttle And Stick) controller, designed to essentially be a fancy joystick/joypad for PC games, but the more I’ve been designing the case, the more I’m inclined to actually make this an extensible, field-reconfigurable radio control handset instead.&lt;/p&gt;
&lt;p&gt;… with joystick functionality if plugged in, of course!&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/robot-controller/proto-square-on.jpg&quot; /&gt;
    &lt;figcaption&gt;A front-on photograph of the controller, hardware all populated, and showing many fingerprints on the screen&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;To support all of this, I had intended to go with the &lt;a href=&quot;https://www.pjrc.com/store/teensy40.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Teensy 4.0&lt;/a&gt; or &lt;a href=&quot;https://www.pjrc.com/store/teensy41.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Teensy 4.1&lt;/a&gt; boards, as both have software support for joysticks with &lt;a href=&quot;https://forum.pjrc.com/threads/23681-Many-axis-joystick&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;amusingly large numbers of inputs&lt;/a&gt;, but now that I’m planning to build this as a proper RC controller, I now wonder if I should go with one of the &lt;a href=&quot;https://www.mikroe.com/mikromedia-3-stm32f4&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Micromedia ‘Smart Display’ devices&lt;/a&gt; as the company supplies &lt;a href=&quot;https://www.mikroe.com/click/wireless-connectivity/4-ghz-transceivers&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;many different radio add-on ‘Click’ boards&lt;/a&gt; so the controller could support a wide range of protocols, software willing.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/robot-controller/stm32-m4-smart-display.jpg&quot; /&gt;
    &lt;figcaption&gt;Image from www.mikroe.com, showing the stm32-m4 smart display platform&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://johnvidler.co.uk/assets/images/robot-controller/mikroe-extension-pcb.png&quot; /&gt;
    &lt;figcaption&gt;Screenshot from www.mikroe.com, showing the extension board with two click boards populated&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Still, I’m very happy with the overall feel of this prototype, and once I’ve decided on a route to take with the controller, I’ll re-print the casing in a higher resolution with some minor fixes included.&lt;/p&gt;
&lt;p&gt;Watch this space 😃&lt;/p&gt;
</content
    >
  </entry>
  <entry>
    <title>Reading RS485 Data From The BMS</title>
    <link href="https://johnvidler.co.uk/blog/reading-rs485-data-from-the-bms/" />
    <updated>2021-06-10T00:00:00Z</updated>
    <id>https://johnvidler.co.uk/blog/reading-rs485-data-from-the-bms/</id>
    <content
      xml:lang=""
      type="html"
      >&lt;p&gt;… I think I need more smarts in my BMS. There are some fun cold-start edge cases for my EV motorbike whereby the system needs to turn on &lt;em&gt;enough&lt;/em&gt; to handle charging the rest of the system, and the BMS just isn’t clever enough to deal with this, so it requires a bit of a bodge via the vehicle management unit (VMU) to kick it into gear.&lt;/p&gt;
&lt;p&gt;No problem, just use the CAN bus or RS485 to talk to the BMS and change its modes.&lt;/p&gt;
&lt;p&gt;But in a frustrating turn of events, it appears that my Battery Management System (BMS) for the EV motorbike does not support CANBus (which is fine, I guess) but also does not support RS485 in the same set of speed ranges as my PLC (which is not!).&lt;/p&gt;
&lt;p&gt;This means that, while my PLC has a native RS485 port, the serial interface it uses for that port cannot be set the locked-in bus frequency for the BMS, so despite them being &lt;em&gt;really close&lt;/em&gt; they’re just different enough data rates to just see mangled data from one another.&lt;/p&gt;
&lt;figure&gt;
    &lt;video controls=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot; autoplay=&quot;&quot;&gt;
        &lt;source src=&quot;https://johnvidler.co.uk/assets/images/bike-rs485-comms/ReadingRS485data.webm&quot; type=&quot;video/mp4&quot; /&gt;
    &lt;/video&gt;
    &lt;figcaption&gt;A terrible video of the console-only interface I&#39;ve written for the REC BMS, running over RS485.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;My ‘fix’ for this, is a dedicated TTL serial to RS485 board, which takes a normal UART and translates it back and forth from RS485 levels. As this board has a more forgiving crystal, and can change speed between the UART one one side and the RS485 bus on the other, it finally lets the PLC talk to the BMS!&lt;/p&gt;
&lt;p&gt;If you have a REC Battery Management System, and want to have a go with my open source software for them, you can find &lt;a href=&quot;https://github.com/JohnVidler/REC-BMS-Control&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;the code over at github&lt;/a&gt;.&lt;/p&gt;
</content
    >
  </entry>
</feed>
