<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Open-Source on Intelligent Dithering</title><link>https://intelligentdithering.com/tags/open-source/</link><description>Overthinking technology so you don't have to</description><generator>Hugo</generator><language>en</language><atom:link href="https://intelligentdithering.com/tags/open-source/index.xml" rel="self" type="application/rss+xml"/><lastBuildDate>Wed, 30 Jul 2025 10:52:46 +0000</lastBuildDate><item><title>Dual Screen DIY CyberDeck</title><link>https://intelligentdithering.com/posts/2025/07/dual-screen-diy-cyberdeck/</link><pubDate>Wed, 30 Jul 2025 10:52:46 +0000</pubDate><guid isPermaLink="false">https://intelligentdithering.com/?p=470</guid><description>A cyberdeck is a custom-built, portable computer, often with a cyberpunk aesthetic, designed for accessing and interacting with cyberspace. In science fiction, they are used by hackers to connect to digital worlds, often for activities like hacking, data theft, or controlling machines. Real-world cyberdecks are typically built around single-board computers and designed to evoke this cyberpunk style and scratch an itch for the maker who designs it.&#10;There are plenty of &amp;ldquo;cyberdeck&amp;rdquo; builds out there but this latest one from Sector 07 has really caught my eye. It is a Dual Screen DIY Cyberdeck built around the Raspberry Pi single board computer featuring twin rotating touchscreens.&#10;</description><content:encoded>&lt;p&gt;A cyberdeck is a custom-built, portable computer, often with a cyberpunk aesthetic, designed for accessing and interacting with cyberspace. In science fiction, they are used by hackers to connect to digital worlds, often for activities like hacking, data theft, or controlling machines. Real-world cyberdecks are typically built around single-board computers and designed to evoke this cyberpunk style and scratch an itch for the maker who designs it.&lt;/p&gt;&#10;&lt;p&gt;There are plenty of &amp;ldquo;cyberdeck&amp;rdquo; builds out there but this latest one from Sector 07 has really caught my eye. It is a Dual Screen DIY Cyberdeck built around the &lt;a href="https://amzn.to/3IT8FU7" target="_blank"&gt;Raspberry Pi single board computer&lt;/a&gt; featuring twin rotating touchscreens.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;This one has it all.&lt;/strong&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Stunning retro-futuristic look&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;a href="https://amzn.to/46unciT" target="_blank"&gt;Dual rotating touch screens&lt;/a&gt;&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Snap-fit 3D printed enclosure&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Access to GPIO for prototyping&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Integrated keyboard&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Open source files and parts so you can build your own&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;a href="https://github.com/sector07-dev/RPI_DEV" target="_blank"&gt;Extensive documentation&lt;/a&gt;&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;The attention to detail that Sector 07 have given to this device is amazing. It looks like a finished product and the aesthetic is super cool.&lt;/p&gt;&#10;&lt;p&gt;Take a break to watch the video below, it really is worth your time and if you decide to build one yourself or have other cyberdecks you think we should know about let us know in the comments.&lt;/p&gt;&#10;&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;&#10;&#9;&#9;&#9;&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/cigAxzQGeLg?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=902" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;&#10;&#9;&#9;&lt;/div&gt;&#10;&#10;</content:encoded></item><item><title>Cheap DIY 8 Port IP KVM on a budget</title><link>https://intelligentdithering.com/posts/2025/01/8-port-ip-kvm-on-a-budget/</link><pubDate>Fri, 31 Jan 2025 00:00:00 +0000</pubDate><guid isPermaLink="false">http://localhost:1313/8-port-ip-kvm-on-a-budget/</guid><description>Building a cheap IP KVM using open source software and Raspberry Pi&#10;DIY IP KVM Parts￼ Step 1: Fit the KVM Switch￼ Step 2: Setup and connect PiKVM￼ Step 3: Reverse engineer the control box!￼ /usr/bin/local/kvm.py /etc/kvmd/override.yaml Conclusion￼ We recently had a small server outage in work. Nothing mission critical, it was over a weekend and coming up to Christmas holidays. It could wait, but that little itch in my brain couldn’t let it sit. I tried several remote remedies to bring it back online but it needed physical access. It had to wait until Monday.&#10;</description><content:encoded>&lt;p&gt;&lt;em&gt;Building a cheap IP KVM using open source software and Raspberry Pi&lt;/em&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="https://intelligentdithering.com/#parts"&gt;DIY IP KVM Parts￼&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://intelligentdithering.com/#step-1-fit-the-kvm-switch"&gt;Step 1: Fit the KVM Switch￼&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://intelligentdithering.com/#step-2-setup-and-connect-pikvm"&gt;Step 2: Setup and connect PiKVM￼&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://intelligentdithering.com/#step-3-reverse-engineer-the-control-box"&gt;Step 3: Reverse engineer the control box!￼&lt;/a&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="https://intelligentdithering.com/#usrbinlocalkvmpy"&gt;/usr/bin/local/kvm.py&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://intelligentdithering.com/#overrideyaml"&gt;/etc/kvmd/override.yaml&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://intelligentdithering.com/#conclusion"&gt;Conclusion￼&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;We recently had a small server outage in work. Nothing mission critical, it was over a weekend and coming up to Christmas holidays. It could wait, but that little itch in my brain couldn’t let it sit. I tried several remote remedies to bring it back online but it needed physical access. It had to wait until Monday.&lt;/p&gt;&#10;&lt;p&gt;We use older Mac Minis as compact Linux servers and they have been working brilliantly for years. And so much quieter than sitting beside a massive rack of noisy servers!&lt;/p&gt;&#10;&lt;p&gt;But if they go down physical access can be a pain as we don’t have a KVM switch. I really wanted to go for an IP KVM switch but they are so expensive! So I figured we could come up with a cheaper solution using, you guessed it, a Raspberry Pi!&lt;/p&gt;&#10;&lt;p&gt;So the plan was to get a cheap 8-port USB and HDMI KVM switch, attach it to a &lt;a href="https://pikvm.org/" target="_blank"&gt;PiKVM&lt;/a&gt; device to get it on the network and Bob’s your uncle, you now have a DIY IP KVM. I hit a few snags along the way but we got it running, so this is documentation of the process for my own records and to help anyone else hoping to replicate this.&lt;/p&gt;&#10;&lt;h2 id="diy-ip-kvm-parts"&gt;DIY IP KVM Parts&lt;a href="https://intelligentdithering.com/#parts"&gt;&lt;/a&gt;&lt;a class="anchorjs-link" href="#diy-ip-kvm-parts"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;🔗 &lt;a href="https://amzn.to/3DOeVKt" target="_blank"&gt;8 port HDMI KVM Switch&lt;/a&gt;&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;🔗 &lt;a href="https://amzn.to/40arRl5" target="_blank"&gt;Raspberry Pi 4&lt;/a&gt;&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;🔗 &lt;a href="https://amzn.to/40avjwb" target="_blank"&gt;Micro SD Card&lt;/a&gt;&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;🔗 &lt;a href="https://amzn.to/40ruccF" target="_blank"&gt;USB-C Power and Data splitter cable&lt;/a&gt;&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;🔗 &lt;a href="https://amzn.to/40pMvz8" target="_blank"&gt;HDMI mirror / splitter&lt;/a&gt;&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;🔗 &lt;a href="https://amzn.to/40u3rV6" target="_blank"&gt;WaveShare HDMI - CSI bridge for Pi&lt;/a&gt;&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;figure&gt;&#10; &lt;a class="paragraph-image"&gt;&#10; &lt;img src="https://intelligentdithering.com/posts/2025/01/8-port-ip-kvm-on-a-budget/images/kvmswitch-1024x896.webp" data-action="zoom" alt="IP KVM using cheap parts and open source" class="lazyload"&gt;&#10; &lt;/a&gt;&#10; &#10;&lt;/figure&gt;&lt;/p&gt;&#10;&lt;h2 id="step-1-fit-the-kvm-switch"&gt;Step 1: Fit the KVM Switch&lt;a href="https://intelligentdithering.com/#step-1-fit-the-kvm-switch"&gt;&lt;/a&gt;&lt;a class="anchorjs-link" href="#step-1-fit-the-kvm-switch"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;This part was the easiest. Just hook up all your servers to the KVM switch and test it out.&lt;/p&gt;&#10;&lt;p&gt;However it was at this point I noticed what could have been a show stopper. Most KVM switches have a key sequence you can use to switch between machines, usually something like tapping Scroll Lock twice and then hitting Escape, or Scroll Lock followed by the number of the port you wish to switch to. This one didn’t! It comes with a switch panel with 8 buttons on it and an IR remote, as well as being able to press the illuminated buttons on the front panel.&lt;/p&gt;&#10;&lt;h2 id="step-2-setup-and-connect-pikvm"&gt;Step 2: Setup and connect PiKVM&lt;a href="https://intelligentdithering.com/#step-2-setup-and-connect-pikvm"&gt;&lt;/a&gt;&lt;a class="anchorjs-link" href="#step-2-setup-and-connect-pikvm"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;This step is well documented at the &lt;a href="https://pikvm.org" target="_blank"&gt;PiKVM website&lt;/a&gt;. Basically download the appropriate image for your Raspberry Pi it will be hosted on (I used &lt;a href="https://intelligentdithering.com/raspberry-pi-5-announced/" target="_blank"&gt;a Pi4&lt;/a&gt;), flash it to an SD card, boot the Pi and then SSH in to configure some options.&lt;/p&gt;&#10;&lt;p&gt;You will also need to connect the WaveShare HDMI capture device to the CSI port on the Pi and connect the HDMI output from the KVM switch to the Pi.&lt;/p&gt;&#10;&lt;p&gt;BONUS TIP: If you connect this via the &lt;a href="https://amzn.to/40pMvz8" target="_blank"&gt;HDMI mirror splitter device&lt;/a&gt;, you can have the display going to the PiKVM AND a physical monitor, which means we can remote in or just use the physical keyboard etc at the server rack.&lt;/p&gt;&#10;&lt;p&gt;Then you will need to connect the power to the PiKVM via the USB-C Power and data splitter cable, so that power goes into the Pi 4 power port and then use a USB-C to A cable to connect the other half to the KVM switch keyboard and mouse port.&lt;/p&gt;&#10;&lt;p&gt;This KVM switch has 4 ports so we are able to connect the PiKVM for control as well as a physical keyboard and mouse.&lt;/p&gt;&#10;&lt;h2 id="step-3-reverse-engineer-the-control-box"&gt;Step 3: Reverse engineer the control box!&lt;a class="anchorjs-link" href="#step-3-reverse-engineer-the-control-box"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;As previously mentioned, the KVM switch did not have keyboard hotkey switching so I couldn’t remotely switch from the PiKVM software. Oops!&lt;/p&gt;&#10;&lt;p&gt;So I took apart the control box that was connected via a USB cable. Unfortunately it doesn’t use the USB protocol, just the cables! Luckily a bit of Googling located someone &lt;a href="https://www.reddit.com/r/pikvm/comments/yt0lne/comment/j92dfmv/?utm_source=share&amp;amp;utm_medium=web3x&amp;amp;utm_name=web3xcss&amp;amp;utm_term=1&amp;amp;utm_content=share_button" target="_blank"&gt;who had already worked out the communication signals it was using&lt;/a&gt;. It seems to send a pulse of varying length to choose the port it switches to.&lt;/p&gt;&#10;&lt;p&gt;I used the &lt;a href="https://gist.github.com/mharsch/52b0a99a945711385fb0120020d8226d" target="_blank"&gt;Python code from here&lt;/a&gt; and saved it to /usr/local/bin/kvm.py making sure to chmod +x to make it executable.&lt;/p&gt;&#10;&lt;p&gt;This &lt;a href="https://www.reddit.com/r/pikvm/comments/yt0lne/comment/kzt0lur/?utm_source=share&amp;amp;utm_medium=web3x&amp;amp;utm_name=web3xcss&amp;amp;utm_term=1&amp;amp;utm_content=share_button" target="_blank"&gt;reddit post&lt;/a&gt; also has some useful pointers.&lt;/p&gt;&#10;&lt;h3 id="usrbinlocalkvmpy"&gt;/usr/bin/local/kvm.py&lt;a class="anchorjs-link" href="#usrbinlocalkvmpy"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;#!/usr/bin/env python&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;import RPi.GPIO as GPIO&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;import sys&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;import time&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;input_pin = 24 # connected to &amp;#39;D+&amp;#39; pin on mini USB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;output_pin = 23 # connected to &amp;#39;D-&amp;#39; pin on mini USB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;def setup():&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;GPIO.setmode(GPIO.BCM)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;GPIO.setwarnings(False)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;GPIO.setup(input_pin, GPIO.IN)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt;GPIO.setup(output_pin, GPIO.OUT)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt;GPIO.output(output_pin, GPIO.HIGH)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt;def get_port() -&amp;gt; int:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt;while GPIO.input(input_pin) == GPIO.LOW:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt;time.sleep(0.001)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt;while GPIO.input(input_pin) == GPIO.HIGH:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt;time.sleep(0.001)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt;start = time.time()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt;while GPIO.input(input_pin) == GPIO.LOW:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt;time.sleep(0.001)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt;stop = time.time()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt;return round((stop - start) * 50)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt;def set_port(port: int):&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt;GPIO.output(output_pin, GPIO.LOW)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt;time.sleep(0.02)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt;GPIO.output(output_pin, GPIO.HIGH)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt;time.sleep(0.02)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt;GPIO.output(output_pin, GPIO.LOW)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33&lt;/span&gt;&lt;span&gt;time.sleep(0.02 * port)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34&lt;/span&gt;&lt;span&gt;GPIO.output(output_pin, GPIO.HIGH)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35&lt;/span&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;36&lt;/span&gt;&lt;span&gt;setup()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;37&lt;/span&gt;&lt;span&gt;set_port(int(sys.argv[1]))&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then in the /etc/kvmd/override.yaml file I added the following:&lt;/p&gt;&#10;&lt;h3 id="etckvmdoverrideyaml"&gt;/etc/kvmd/override.yaml&lt;a class="anchorjs-link" href="#etckvmdoverrideyaml"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;kvmd:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt; gpio:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt; drivers:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt; kvm_set_input_1:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt; type: cmd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt; cmd: [/usr/bin/sudo, /usr/local/bin/kvm.py, 1]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt; kvm_set_input_2:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt; type: cmd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt; cmd: [/usr/bin/sudo, /usr/local/bin/kvm.py, 2]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt; kvm_set_input_3:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt; type: cmd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt; cmd: [/usr/bin/sudo, /usr/local/bin/kvm.py, 3]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&lt;/span&gt;&lt;span&gt; kvm_set_input_4:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&lt;/span&gt;&lt;span&gt; type: cmd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&lt;/span&gt;&lt;span&gt; cmd: [/usr/bin/sudo, /usr/local/bin/kvm.py, 4]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16&lt;/span&gt;&lt;span&gt; kvm_set_input_5:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17&lt;/span&gt;&lt;span&gt; type: cmd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18&lt;/span&gt;&lt;span&gt; cmd: [/usr/bin/sudo, /usr/local/bin/kvm.py, 5]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19&lt;/span&gt;&lt;span&gt; kvm_set_input_6:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20&lt;/span&gt;&lt;span&gt; type: cmd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21&lt;/span&gt;&lt;span&gt; cmd: [/usr/bin/sudo, /usr/local/bin/kvm.py, 6]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22&lt;/span&gt;&lt;span&gt; kvm_set_input_7:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23&lt;/span&gt;&lt;span&gt; type: cmd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24&lt;/span&gt;&lt;span&gt; cmd: [/usr/bin/sudo, /usr/local/bin/kvm.py, 7]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25&lt;/span&gt;&lt;span&gt; kvm_set_input_8:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26&lt;/span&gt;&lt;span&gt; type: cmd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27&lt;/span&gt;&lt;span&gt; cmd: [/usr/bin/sudo, /usr/local/bin/kvm.py, 8]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28&lt;/span&gt;&lt;span&gt; scheme:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29&lt;/span&gt;&lt;span&gt; kvm_input_1_button:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30&lt;/span&gt;&lt;span&gt; driver: kvm_set_input_1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31&lt;/span&gt;&lt;span&gt; pin: 0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32&lt;/span&gt;&lt;span&gt; mode: output&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33&lt;/span&gt;&lt;span&gt; switch: false&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34&lt;/span&gt;&lt;span&gt; kvm_input_2_button:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35&lt;/span&gt;&lt;span&gt; driver: kvm_set_input_2&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;36&lt;/span&gt;&lt;span&gt; pin: 0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;37&lt;/span&gt;&lt;span&gt; mode: output&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;38&lt;/span&gt;&lt;span&gt; switch: false&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;39&lt;/span&gt;&lt;span&gt; kvm_input_3_button:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;40&lt;/span&gt;&lt;span&gt; driver: kvm_set_input_3&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;41&lt;/span&gt;&lt;span&gt; pin: 0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;42&lt;/span&gt;&lt;span&gt; mode: output&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;43&lt;/span&gt;&lt;span&gt; switch: false&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;44&lt;/span&gt;&lt;span&gt; kvm_input_4_button:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;45&lt;/span&gt;&lt;span&gt; driver: kvm_set_input_4&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;46&lt;/span&gt;&lt;span&gt; pin: 0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;47&lt;/span&gt;&lt;span&gt; mode: output&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;48&lt;/span&gt;&lt;span&gt; switch: false&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;49&lt;/span&gt;&lt;span&gt; kvm_input_5_button:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;50&lt;/span&gt;&lt;span&gt; driver: kvm_set_input_5&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;51&lt;/span&gt;&lt;span&gt; pin: 0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;52&lt;/span&gt;&lt;span&gt; mode: output&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;53&lt;/span&gt;&lt;span&gt; switch: false&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;54&lt;/span&gt;&lt;span&gt; kvm_input_6_button:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;55&lt;/span&gt;&lt;span&gt; driver: kvm_set_input_6&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;56&lt;/span&gt;&lt;span&gt; pin: 0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;57&lt;/span&gt;&lt;span&gt; mode: output&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;58&lt;/span&gt;&lt;span&gt; switch: false&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;59&lt;/span&gt;&lt;span&gt; kvm_input_7_button:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;60&lt;/span&gt;&lt;span&gt; driver: kvm_set_input_7&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;61&lt;/span&gt;&lt;span&gt; pin: 0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;62&lt;/span&gt;&lt;span&gt; mode: output&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;63&lt;/span&gt;&lt;span&gt; switch: false&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;64&lt;/span&gt;&lt;span&gt; kvm_input_8_button:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;65&lt;/span&gt;&lt;span&gt; driver: kvm_set_input_8&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;66&lt;/span&gt;&lt;span&gt; pin: 0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;67&lt;/span&gt;&lt;span&gt; mode: output&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;68&lt;/span&gt;&lt;span&gt; switch: false&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;69&lt;/span&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;70&lt;/span&gt;&lt;span&gt; view:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;71&lt;/span&gt;&lt;span&gt; header:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;72&lt;/span&gt;&lt;span&gt; title: Input&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;73&lt;/span&gt;&lt;span&gt; table:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;74&lt;/span&gt;&lt;span&gt; - [&amp;#34;#Console:&amp;#34;, &amp;#34;kvm_input_1_button|Prox1&amp;#34;, &amp;#34;kvm_input_2_button|Prox2&amp;#34;, &amp;#34;kvm_input_3_button|Prox3&amp;#34;, &amp;#34;kvm_input_4_button|Lambda&amp;#34;, &amp;#34;kvm_input_5_button|NA01&amp;#34;, &amp;#34;kvm_input_6_button|NA02&amp;#34;, &amp;#34;kvm_input_7_button|ProxBackup&amp;#34;, &amp;#34;kvm_input_8_button|FOG&amp;#34;]&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The bottom section labelled “view” creates a new button in the top menu of PiKVM called Input, and then it has 8 buttons within it. The names of the buttons are Prox1, Prox2 etc. You should change those to the names of the machines you have connected to each port.&lt;/p&gt;&#10;&lt;p&gt;Then I cut open an old Mini-USB cable and exposed the data lines. You do not need the red or black power lines. I soldered on DuPont connectors and attached the data lines to pins 23 and 24 on the Pi GPIO pins.&lt;/p&gt;&#10;&lt;p&gt;&lt;figure&gt;&#10; &lt;a class="paragraph-image"&gt;&#10; &lt;img src="https://intelligentdithering.com/posts/2025/01/8-port-ip-kvm-on-a-budget/images/IMG_2583.jpeg" data-action="zoom" alt="" class="lazyload"&gt;&#10; &lt;/a&gt;&#10; &#10;&lt;/figure&gt;&lt;/p&gt;&#10;&lt;p&gt;I then tested the switching using the kvm.py script above from the command line. Bingo!&lt;/p&gt;&#10;&lt;h2 id="conclusion"&gt;Conclusion&lt;a href="https://intelligentdithering.com/#conclusion"&gt;&lt;/a&gt;&lt;a class="anchorjs-link" href="#conclusion"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;It was a lot of fiddling about but we now have web based IP KVM access to all of our servers and the ability to easily switch between them in the web interface.&lt;/p&gt;&#10;&lt;p&gt;PiKVM also has the ability to emulate a USB disk or CD drive, so you can upload ISOs to it and attach them, allowing you to fully reimage a machine remotely. It really is a fantastic project and I am glad it exists!&lt;/p&gt;&#10;</content:encoded></item><item><title>Make the ultimate bootable USB drive</title><link>https://intelligentdithering.com/posts/2023/10/make-the-ultimate-bootable-usb-drive/</link><pubDate>Sun, 15 Oct 2023 00:00:00 +0000</pubDate><guid isPermaLink="false">http://localhost:1313/make-the-ultimate-bootable-usb-drive/</guid><description>Creating a USB Swiss army knife full of tech tools for all your geeky needs&#10;Today we are going to make the ultimate bootable USB drive to have with you at all times. This is an invaluable tool and it is all made possible by the Open Source tool Ventoy.&#10;This post is available in video form on YouTube as well for the visual learners among us.&#10;Ventoy is basically a bootloader that goes onto a USB drive that allows you to easily boot from any of the ISO disc images contained within it. This allows you to have a single USB drive with all of the tools you need on it, Windows installer images, file rescue kits, hacking tools etc.&#10;</description><content:encoded>&lt;p&gt;&lt;em&gt;Creating a USB Swiss army knife full of tech tools for all your geeky needs&lt;/em&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;figure&gt;&#10; &lt;a class="paragraph-image"&gt;&#10; &lt;img src="https://intelligentdithering.com/posts/2023/10/make-the-ultimate-bootable-usb-drive/images/image-2-1024x682.png" data-action="zoom" alt="" class="lazyload"&gt;&#10; &lt;/a&gt;&#10; &#10;&lt;/figure&gt;&lt;/p&gt;&#10;&lt;p&gt;Today we are going to make the ultimate bootable USB drive to have with you at all times. This is an invaluable tool and it is all made possible by the Open Source tool &lt;a href="https://ventoy.net" target="_blank"&gt;Ventoy&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;This post is available in video form on YouTube as well for the visual learners among us.&lt;/p&gt;&#10;&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;&#10;&#9;&#9;&#9;&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/eEQJGVzGQqk?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;&#10;&#9;&#9;&lt;/div&gt;&#10;&#10;&lt;p&gt;Ventoy is basically a bootloader that goes onto a USB drive that allows you to easily boot from any of the ISO disc images contained within it. This allows you to have a single USB drive with all of the tools you need on it, Windows installer images, file rescue kits, hacking tools etc.&lt;/p&gt;&#10;&lt;p&gt;It lets you make a personalised USB Swiss army knife of all the tools you use most often.&lt;/p&gt;&#10;&lt;h2 id="preparation-to-make-the-bootable-usb-drive"&gt;Preparation to make the bootable USB drive&lt;a href="https://intelligentdithering.com/#preparation-to-make-the-bootable-usb-drive"&gt;&lt;/a&gt;&lt;a class="anchorjs-link" href="#preparation-to-make-the-bootable-usb-drive"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;What do we need to begin:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;strong&gt;A USB drive to hold our ultimate bootable USB toolkit&lt;/strong&gt;&lt;br&gt;&#10;I find that keeping the drive below 128GB helps with compatibility with some older BIOS versions. I found &lt;a href="https://amzn.to/3s1rVGK" target="_blank"&gt;this great&lt;/a&gt; &lt;a href="https://amzn.to/3tTzfEV" target="_blank"&gt;little&lt;/a&gt; &lt;a href="https://amzn.to/3s1rVGK" target="_blank"&gt;drive&lt;/a&gt; &lt;a href="https://amzn.to/3MlhHYI" target="_blank"&gt;on&lt;/a&gt; &lt;a href="https://amzn.to/3s1rVGK" target="_blank"&gt;Amazon&lt;/a&gt; that I use personally&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;strong&gt;The Ventoy application&lt;/strong&gt;&lt;br&gt;&#10;You can get this from &lt;a href="https://ventoy.net" target="_blank"&gt;Ventoy.net&lt;/a&gt; for either Linux or Windows. Download the appropriate file and extract the contents of the zip file.&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;strong&gt;ISO files you want to boot from&lt;/strong&gt;&lt;br&gt;&#10;You will need some disk images that you want to put onto the bootable USB drive. I would recommend things like the &lt;a href="https://www.microsoft.com/en-gb/software-download/windows10" target="_blank"&gt;Windows installer DVDs&lt;/a&gt;, &lt;a href="https://www.hirensbootcd.org" target="_blank"&gt;Hirens BootCD&lt;/a&gt;, &lt;a href="https://clonezilla.org" target="_blank"&gt;Clonezilla&lt;/a&gt;, SystemRescue etc. Maybe even a &lt;a href="https://ubuntu.com/tutorials/try-ubuntu-before-you-install#1-getting-started" target="_blank"&gt;Ubuntu Live CD&lt;/a&gt; would be useful!&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="creating-the-bootable-usb-drive"&gt;Creating the bootable USB drive&lt;a href="https://intelligentdithering.com/#creating-the-bootable-usb-drive"&gt;&lt;/a&gt;&lt;a class="anchorjs-link" href="#creating-the-bootable-usb-drive"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Once you have the Ventoy application downloaded, extract the files and run the file called Ventoy2Disk.exe&lt;/p&gt;&#10;&lt;p&gt;You will get a window like the one below.&lt;/p&gt;&#10;&lt;p&gt;&lt;figure&gt;&#10; &lt;a class="paragraph-image"&gt;&#10; &lt;img src="https://intelligentdithering.com/posts/2023/10/make-the-ultimate-bootable-usb-drive/images/image-3.png" data-action="zoom" alt="" class="lazyload"&gt;&#10; &lt;/a&gt;&#10; &#10;&lt;/figure&gt;&lt;/p&gt;&#10;&lt;p&gt;Choose your bootable USB drive in the dropdown and &lt;strong&gt;double check to make sure it is the right one&lt;/strong&gt;. This tool will destroy all data on the drive so be very sure at this stage!&lt;/p&gt;&#10;&lt;p&gt;Click &lt;strong&gt;Install&lt;/strong&gt;. It will warn you twice that it is going to wipe the drive before proceeding. The process only takes 20 seconds or so.&lt;/p&gt;&#10;&lt;p&gt;Once it has completed you will have a new USB drive show up in Windows Explorer named Ventoy.&lt;/p&gt;&#10;&lt;p&gt;Now all you have to do is copy over your ISO files to that drive. It really is that simple!&lt;/p&gt;&#10;&lt;p&gt;If you need to update or add a new ISO file in the future, just plug the drive in and copy the files over. You do not need to run the Ventoy2Disk app again unless you wish to update the Ventoy boot loader (perhaps if they release updates to fix bugs on certain systems)&lt;/p&gt;&#10;&lt;h2 id="using-your-new-bootable-usb-drive"&gt;Using your new bootable USB drive&lt;a href="https://intelligentdithering.com/#using-your-new-bootable-usb-drive"&gt;&lt;/a&gt;&lt;a class="anchorjs-link" href="#using-your-new-bootable-usb-drive"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Once you have made the drive and copied over some ISO files now you just need to try it out.&lt;/p&gt;&#10;&lt;p&gt;Plug the drive into a computer and turn it on. If the computer is set to boot from USB drives, the Ventoy boot window will appear. If not you may have to press the appropriate key to bring up the boot menu on your computer (typically one of the top row function keys)&lt;/p&gt;&#10;&lt;p&gt;&lt;figure&gt;&#10; &lt;a class="paragraph-image"&gt;&#10; &lt;img src="https://intelligentdithering.com/posts/2023/10/make-the-ultimate-bootable-usb-drive/images/image-4-1024x574.png" data-action="zoom" alt="" class="lazyload"&gt;&#10; &lt;/a&gt;&#10; &#10;&lt;/figure&gt;&lt;/p&gt;&#10;&lt;p&gt;When the Ventoy window appears, simply choose the ISO you wish to boot from and hit Return. It really is that easy!&lt;/p&gt;&#10;&lt;p&gt;No more lugging around a bag full of poorly labelled USB drives with every possible Windows or Linux install on them. Everything in one place on your new Swiss army knife of IT tools!&lt;/p&gt;&#10;&lt;p&gt;Let me know if you find this useful and what tools you like to put on your bootable USB disk.&lt;/p&gt;&#10;</content:encoded></item><item><title>Free Digital Signage with Raspberry Pi and Google Slides</title><link>https://intelligentdithering.com/posts/2023/09/free-digital-signage-with-raspberry-pi-and-google-slides/</link><pubDate>Wed, 27 Sep 2023 00:00:00 +0000</pubDate><guid isPermaLink="false">http://localhost:1313/free-digital-signage-with-raspberry-pi-and-google-slides/</guid><description>Using a Raspberry Pi with Google Slides is an excellent way to make very cheap and effective digital signage. In this guide I will show you how to build this. This is an updated method as the Screenly / Anthias software doesn’t seem to like 4K screens for Google Slides! And the beauty of it: once you set it up, you don’t have to touch the Pi again, just edit the Google Slides presentation and watch your screens update!&#10;</description><content:encoded>&lt;p&gt;Using a Raspberry Pi with Google Slides is an excellent way to make very cheap and effective digital signage. In this guide I will show you how to build this. This is an updated method as the Screenly / Anthias software doesn’t seem to like 4K screens for Google Slides! And the beauty of it: once you set it up, you don’t have to touch the Pi again, just edit the Google Slides presentation and watch your screens update!&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;UPDATE: The Raspberry Pi Trading Company have just announced the release of the Raspberry Pi 5. &lt;a href="https://intelligentdithering.com/raspberry-pi-5-announced/" target="_blank"&gt;Read all about it on my new post here&lt;/a&gt;. (It can run dual 4K displays, so it will be perfect for your next digital signage project!)&lt;/strong&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="https://intelligentdithering.com/#what-you-need"&gt;What you need:￼&lt;/a&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="https://intelligentdithering.com/#step-1-prepare-your-google-slides-presentation-for-digital-signage"&gt;Step 1: Prepare your Google Slides presentation for Digital Signage￼&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://intelligentdithering.com/#step-2-prepare-the-sd-card"&gt;Step 2: Prepare the SD Card￼&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://intelligentdithering.com/#step-3-log-in-and-setup-the-pi"&gt;Step 3: Log in and setup the Pi￼&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://intelligentdithering.com/#bonus-step-auto-power-off-and-on"&gt;Bonus step: Auto power off and on￼&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;figure&gt;&#10; &lt;a class="paragraph-image"&gt;&#10; &lt;img src="https://intelligentdithering.com/posts/2023/09/free-digital-signage-with-raspberry-pi-and-google-slides/images/Series-E235_Digital-Signage-1024x683.webp" data-action="zoom" alt="Digital Signage in action" class="lazyload"&gt;&#10; &lt;/a&gt;&#10; &#10;&lt;/figure&gt;&lt;/p&gt;&#10;&lt;h2 id="what-you-need"&gt;What you need:&lt;a href="https://intelligentdithering.com/#what-you-need"&gt;&lt;/a&gt;&lt;a class="anchorjs-link" href="#what-you-need"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;a href="https://amzn.to/458Ooze" target="_blank"&gt;Raspberry Pi 4&lt;/a&gt; and power adaptors etc&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;a href="https://amzn.to/48vV4uc" target="_blank"&gt;Big screen or TV&lt;/a&gt;&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;a href="https://amzn.to/3ZyYyrO" target="_blank"&gt;SD Card 8GB or larger&lt;/a&gt;&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Google account&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;About 30 minutes!&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="step-1-prepare-your-google-slides-presentation-for-digital-signage"&gt;Step 1: Prepare your Google Slides presentation for Digital Signage&lt;a href="https://intelligentdithering.com/#step-1-prepare-your-google-slides-presentation-for-digital-signage"&gt;&lt;/a&gt;&lt;a class="anchorjs-link" href="#step-1-prepare-your-google-slides-presentation-for-digital-signage"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Before we start, you should have a Google Slides presentation prepared that you want to show on your digital signage. Make the presentation with no transitions or timings, as it will be set to the same timings for every slide in the sharing phase.&lt;/p&gt;&#10;&lt;p&gt;Once you are happy with your slides, click on File -&amp;gt; Share -&amp;gt; Publish to Web. Then choose to advance slides every X seconds (set it to 5 if just images, longer if your slides will have a lot of text to read)&lt;/p&gt;&#10;&lt;p&gt;Make sure that the “Start slideshow as soon as the player loads” and&lt;br&gt;&#10;“Restart the slideshow after the last slide” boxes are ticked.&lt;/p&gt;&#10;&lt;p&gt;Then click Publish.&lt;/p&gt;&#10;&lt;p&gt;Copy the URL that is shown and save it somewhere you can get later.&lt;/p&gt;&#10;&lt;h3 id="step-2-prepare-the-sd-card"&gt;Step 2: Prepare the SD Card&lt;a href="https://intelligentdithering.com/#step-2-prepare-the-sd-card"&gt;&lt;/a&gt;&lt;a class="anchorjs-link" href="#step-2-prepare-the-sd-card"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Download Raspberry Pi Imager from &lt;a href="https://www.raspberrypi.com/software/" target="_blank"&gt;https://&lt;/a&gt;&lt;a href="https://www.raspberrypi.com/software/" target="_blank"&gt;www.raspberrypi.com&lt;/a&gt;&lt;a href="https://www.raspberrypi.com/software/" target="_blank"&gt;/software/&lt;/a&gt;&lt;/p&gt;&#10;&lt;figure&gt;&#10;&lt;p&gt;&lt;figure&gt;&#10; &lt;a class="paragraph-image"&gt;&#10; &lt;img src="https://intelligentdithering.com/posts/2023/09/free-digital-signage-with-raspberry-pi-and-google-slides/images/Untitled.gif" data-action="zoom" alt="" class="lazyload"&gt;&#10; &lt;/a&gt;&#10; &#10;&lt;/figure&gt;&lt;/p&gt;&#10;&lt;figcaption&gt;&#10;&lt;p&gt;Preparing the SD Card for your Digital Signage&lt;/p&gt;&#10;&lt;/figcaption&gt;&#10;&lt;/figure&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Click on Choose OS&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Select Raspberry Pi OS (other)&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Select Raspberry Pi OS Lite (64-bit)&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Select Choose Storage&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Choose your memory card from the list (be careful not to select the wrong drive!)&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Click on the gear icon&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Choose a hostname for the device&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Enable SSH using password authentication&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Set the username and password&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Configure Wireless if you will be using it (I use Ethernet for a more reliable connection)&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Set Locale Settings (not essential but makes date and time correct)&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Hit Save&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Now click Write to wipe and install on the SD Card&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Once complete, put the card in to the Raspberry Pi and fire it up.&lt;/p&gt;&#10;&lt;h3 id="step-3-log-in-and-setup-the-pi"&gt;Step 3: Log in and setup the Pi&lt;a href="https://intelligentdithering.com/#step-3-log-in-and-setup-the-pi"&gt;&lt;/a&gt;&lt;a class="anchorjs-link" href="#step-3-log-in-and-setup-the-pi"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Log in using SSH with whatever username and host name you gave the Digital Signage Pi during the SD Card prep phase. For example “&lt;code&gt;ssh Colin@digitalsign.local&lt;/code&gt;”&lt;/p&gt;&#10;&lt;p&gt;Update the software on the Pi first by using the following command&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will update the Pi software list followed by installing all of the missing updates. The -y on the end just tells it to go ahead without prompting you for confirmation.&lt;/p&gt;&#10;&lt;p&gt;Once this is done we will install the packages needed to put our Pi into Kiosk mode. We will install Chromium browser and set it up to launch a webpage (our Google slides presentation) and make that page fullscreen.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;sudo apt install --no-install-recommends xserver-xorg x11-xserver-utils xinit openbox chromium-browser -y&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once this installation has completed we just need to configure the browser to launch at login and tweak a few other settings.&lt;/p&gt;&#10;&lt;p&gt;First of all we need to make sure the Pi is in the correct graphics mode. Do this by editing the config.txt file in the boot folder.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;sudo nano /boot/config.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;or on the newer BookWorm Pi OS Lite&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;sudo nano /boot/firmware/config.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Look through the file to find the line similar to&lt;br&gt;&#10;dtoverlay=vc4-kms-v3d&lt;/p&gt;&#10;&lt;p&gt;Make sure that it reads dtoverlay=vc4-&lt;strong&gt;fkms&lt;/strong&gt;-v3d and NOT &lt;strong&gt;kms&lt;/strong&gt; (that little f is very important, without it the slides can be a little jerky)&lt;/p&gt;&#10;&lt;p&gt;Once that is done, save the file by pressing Ctrl-O then Return to save and then Ctrl-X to exit.&lt;/p&gt;&#10;&lt;p&gt;Next we will edit the file /etc/xdg/openbox/autostart using the command below.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;sudo nano /etc/xdg/openbox/autostart&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And then copy and paste the following code into the file, making sure to edit the “your-url-here” bit at the end. In here you want to paste the Google slides publish URL we got in Step 1.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&lt;/span&gt;&lt;span&gt;# Disable screen saver / screen blanking / power management&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&lt;/span&gt;&lt;span&gt;xset s off&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&lt;/span&gt;&lt;span&gt;xset s noblank&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&lt;/span&gt;&lt;span&gt;xset -dpms&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&lt;/span&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&lt;/span&gt;&lt;span&gt;#Allow quitting the X server with CTRL-ATL-Backspace&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&lt;/span&gt;&lt;span&gt;setxkbmap -option terminate:ctrl_alt_bksp&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&lt;/span&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&lt;/span&gt;&lt;span&gt;#Start Chromium browser in kiosk mode&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&lt;/span&gt;&lt;span&gt;sed -i &amp;#39;s/&amp;#34;exited_cleanly&amp;#34;:false/&amp;#34;exited_cleanly&amp;#34;:true/&amp;#39; ~/.config/chromium/&amp;#39;Local State&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&lt;/span&gt;&lt;span&gt;sed -i &amp;#39;s/&amp;#34;exited_cleanly&amp;#34;:false/&amp;#34;exited_cleanly&amp;#34;:true/; s/&amp;#34;exit_type&amp;#34;:&amp;#34;[^&amp;#34;]+&amp;#34;/&amp;#34;exit_type&amp;#34;:&amp;#34;Normal&amp;#34;/&amp;#39; ~/.config/chromium/Default/Preferences&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&lt;/span&gt;&lt;span&gt;chromium-browser --disable-infobars --kiosk &amp;#39;http://your-url-here&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Again, Ctrl-O and Return to save the file and then Ctrl-X to exit nano.&lt;/p&gt;&#10;&lt;p&gt;Next we will make the X server start on login. Edit the .bash_profile file by doing&lt;br&gt;&#10;&lt;code&gt;nano ~/.bash_profile&lt;/code&gt; and pasting the following code and saving using Ctrl-O then Return followed by Ctrl-X to exit.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;[[ -z $DISPLAY &amp;amp;&amp;amp; $XDG_VTNR -eq 1 ]] &amp;amp;&amp;amp; startx -- -nocursor&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we need to tell the Pi to autologin every time it restarts so that the slides will display automatically. Do this by running &lt;code&gt;sudo raspi-config&lt;/code&gt;.&lt;/p&gt;&#10;&lt;p&gt;In the text menus that appear choose &lt;strong&gt;1. System Options&lt;/strong&gt;, then &lt;strong&gt;S5 Boot / Auto Login&lt;/strong&gt; and then choose &lt;strong&gt;B2 Console Autologin&lt;/strong&gt;&lt;br&gt;&#10;Then press Tab twice to highlight Finish and hit Return. When asked to reboot choose Yes.&lt;/p&gt;&#10;&lt;p&gt;The Pi will now reboot and when it comes back on it should auto login in start to display your slides!&lt;/p&gt;&#10;&lt;p&gt;Congratulations! You have just built a very cheap and fast digital signage solution. Hook it up to a nice big TV and you are off!&lt;/p&gt;&#10;&lt;h3 id="bonus-step-auto-power-off-and-on"&gt;Bonus step: Auto power off and on&lt;a href="https://intelligentdithering.com/#bonus-step-auto-power-off-and-on"&gt;&lt;/a&gt;&lt;a class="anchorjs-link" href="#bonus-step-auto-power-off-and-on"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;When I use this method to make digital signage I like to use the crontab to turn the display off and on using a schedule. Most modern TVs will go into standby mode when the HDMI source turns off, saving energy when your display is not in use.&lt;/p&gt;&#10;&lt;p&gt;To edit the crontab use &lt;code&gt;sudo crontab -e&lt;/code&gt;&lt;/p&gt;&#10;&lt;p&gt;If it is your first time it will ask what you want to use to edit it, I suggest nano as we are used to this from previous steps.&lt;/p&gt;&#10;&lt;p&gt;Here is the crontab I use&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;#reboot the Pi Mon-Fri at 8am. This refreshes the slides and ensures the TV wakes up&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&lt;/span&gt;&lt;span&gt;0 8 * * 1-5 sudo reboot &amp;gt;/dev/null 2&amp;gt;&amp;amp;1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&lt;/span&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&lt;/span&gt;&lt;span&gt;#this turns the display output on&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&lt;/span&gt;&lt;span&gt;15 8 * * 1-5 sudo vcgencmd display_power 1 &amp;gt;/dev/null 2&amp;gt;&amp;amp;1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&lt;/span&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&lt;/span&gt;&lt;span&gt;#Disable HDMI end of day Mon - Fri 530pm. TV should go to sleep after&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&lt;/span&gt;&lt;span&gt;30 17 * * 1-5 sudo vcgencmd display_power 0 &amp;gt;/dev/null 2&amp;gt;&amp;amp;1&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I hope this guide is useful to you, please share it and let me know how you use your Pi in digital signage!&lt;/p&gt;&#10;</content:encoded></item><item><title>Teaching with Moodle: An Introduction</title><link>https://intelligentdithering.com/posts/2017/01/teaching-with-moodle-an-introduction/</link><pubDate>Tue, 03 Jan 2017 00:00:00 +0000</pubDate><guid isPermaLink="false">http://localhost:1313/teaching-with-moodle-an-introduction/</guid><description>If you are a beginner to the Moodle Learning Management System or even a current user just wishing to update and hone their skills then I can highly recommend this free online course delivered by the Moodle team themselves.&#10;The course will take you through the basics of using Moodle to deliver Learning and Teaching to your students and showcases some of the excellent widgets and tools on offer.&#10;And because the course is run on Moodle itself, you get to experience the learning as a student would on your course. I found this perspective really helped spark some ideas for ways to deliver content to make it more fun and engaging.&#10;</description><content:encoded>&lt;p&gt;If you are a beginner to the &lt;a href="http://www.moodle.org" target="_blank"&gt;Moodle Learning Management System&lt;/a&gt; or even a current user just wishing to update and hone their skills then I can highly recommend this free online course delivered by the Moodle team themselves.&lt;/p&gt;&#10;&lt;p&gt;The course will take you through the basics of using Moodle to deliver Learning and Teaching to your students and showcases some of the excellent widgets and tools on offer.&lt;/p&gt;&#10;&lt;p&gt;And because the course is run on Moodle itself, you get to experience the learning as a student would on your course. I found this perspective really helped spark some ideas for ways to deliver content to make it more fun and engaging.&lt;/p&gt;&#10;&lt;p&gt;&lt;a href="https://learn.moodle.net/login/signup.php" target="_blank"&gt;You can sign up here&lt;/a&gt; but as there are peer assessed sections you need get signed up this week to make sure you don’t miss any deadlines. They run these courses approximately every 6 months.&lt;/p&gt;&#10;&lt;p&gt;The course is free and should only require 3-4 hours per week of time (probably less if you have used Moodle before). The community engagement aspect will also allow you to see how Moodle is used in a variety of learning environments and you will leave enthused and bursting with ideas!&lt;/p&gt;&#10;&lt;p&gt;Here is a copy of the course outline. You also get a digital certificate on completion of the course, which you may be able to use towards whatever form of Professional Development scheme your institution operates.&lt;/p&gt;&#10;&lt;p&gt;&lt;figure&gt;&#10; &lt;a class="paragraph-image"&gt;&#10; &lt;img src="https://intelligentdithering.com/posts/2017/01/teaching-with-moodle-an-introduction/images/image-1024x583.png" data-action="zoom" alt="" class="lazyload"&gt;&#10; &lt;/a&gt;&#10; &#10;&lt;/figure&gt;&lt;/p&gt;&#10;</content:encoded></item></channel></rss>