<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://blog.jojotodos.net/feed.xml" rel="self" type="application/atom+xml" /><link href="https://blog.jojotodos.net/" rel="alternate" type="text/html" /><updated>2026-04-22T08:42:31+00:00</updated><id>https://blog.jojotodos.net/feed.xml</id><title type="html">PARA TODOS</title><subtitle>J0J0&apos;s blog for all</subtitle><entry><title type="html">DiscoDOS sells 3 times pretty</title><link href="https://blog.jojotodos.net/discodos3/" rel="alternate" type="text/html" title="DiscoDOS sells 3 times pretty" /><published>2025-02-04T00:00:00+00:00</published><updated>2025-02-04T00:00:00+00:00</updated><id>https://blog.jojotodos.net/discodos3</id><content type="html" xml:base="https://blog.jojotodos.net/discodos3/"><![CDATA[<p>It sells your records on the Discogs Marketplace - and looks darn good doing it!</p>

<p>Of course you should <a href="https://github.com/JOJ0/discodos/blob/master/README.md">read the project description</a> to understand what this software even is. Of course you should read release notes for <a href="https://github.com/JOJ0/discodos/releases/tag/v3.0">3.0</a> and <a href="https://github.com/JOJ0/discodos/releases/tag/v3.1.0">3.1</a> to learn its latest features. Of course you should head straight to the <a href="https://discodos.readthedocs.io/en/latest/QUICKSTART.html">quickstart guide</a>, to see how to use it…..but why not only stare at all these tiny pink television screens and enjoy the show - DiscoDOS your <em>Disco Operator Softie</em> loves you! &lt;3</p>

<p><a name="chapter_1"></a></p>

<h2 id="gif-love">Gif Love</h2>

<div class="photo-gallery-frame clearfix">
  <ul class="photo-gallery-list">
    
    <li>
      <a href="/discodos3/01/" name="01">
        <img src="/images/2025-2-4-discodos3/01.gif" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/discodos3/02/" name="02">
        <img src="/images/2025-2-4-discodos3/02.gif" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/discodos3/03/" name="03">
        <img src="/images/2025-2-4-discodos3/03.gif" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/discodos3/04/" name="04">
        <img src="/images/2025-2-4-discodos3/04.gif" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/discodos3/05/" name="05">
        <img src="/images/2025-2-4-discodos3/05.gif" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/discodos3/06/" name="06">
        <img src="/images/2025-2-4-discodos3/06.gif" alt="" style="width: 31%" />
      </a>
    </li>
    
  </ul>
</div>

<h2 id="screenshot-love">Screenshot Love</h2>

<figure class="sidebyside" style="width: 100%; float: none; margin: 0; ">
  <a href="/images/2025-2-4-discodos3/shot01.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2025-2-4-discodos3/shot01-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;"></figcaption>
</figure>

<div style="display: block; text-align: center;">



<figure class="sidebyside" style="width: 60%; float: none; margin: 0; display: inline-block;">
  <a href="/images/2025-2-4-discodos3/shot02.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2025-2-4-discodos3/shot02-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;"></figcaption>
</figure>



</div>

<figure class="sidebyside" style="width: 100%; float: none; margin: 0; ">
  <a href="/images/2025-2-4-discodos3/shot03.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2025-2-4-discodos3/shot03-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;"></figcaption>
</figure>

<h2 id="this-is-for-you">This is for you?</h2>

<ul>
  <li><a href="https://discodos.readthedocs.io/en/latest/QUICKSTART.html">Quickstart</a></li>
  <li><a href="https://discodos.jojotodos.net">Website / Roadmap</a></li>
</ul>]]></content><author><name></name></author><summary type="html"><![CDATA[It sells your records on the Discogs Marketplace - and looks darn good doing it!]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.jojotodos.net/images/2025-2-4-discodos3/shot01.jpg" /><media:content medium="image" url="https://blog.jojotodos.net/images/2025-2-4-discodos3/shot01.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">No music’s on the blog (The Giovanni Mix)</title><link href="https://blog.jojotodos.net/no-music/" rel="alternate" type="text/html" title="No music’s on the blog (The Giovanni Mix)" /><published>2024-11-11T00:00:00+00:00</published><updated>2024-11-11T00:00:00+00:00</updated><id>https://blog.jojotodos.net/no-music</id><content type="html" xml:base="https://blog.jojotodos.net/no-music/"><![CDATA[<p>Why is there no music on this blog? After all it is about music tinkering and stuff! Well, you are right, there should be music and now there is.</p>

<iframe width="100%" height="150" scrolling="no" frameborder="no" allow="autoplay" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/1970014867&amp;color=%236c747e&amp;auto_play=false&amp;hide_related=false&amp;show_comments=true&amp;show_user=true&amp;show_reposts=false&amp;show_teaser=true&amp;visual=true"></iframe>
<div style="font-size: 10px; color: #cccccc;line-break: anywhere;word-break: normal;overflow: hidden;white-space: nowrap;text-overflow: ellipsis; font-family: Interstate,Lucida Grande,Lucida Sans Unicode,Lucida Sans,Garuda,Verdana,Tahoma,sans-serif;font-weight: 100;"><a href="https://soundcloud.com/jojotodos" title="J0J0 Todos presents" target="_blank" style="color: #cccccc; text-decoration: none;">J0J0 Todos presents</a> · <a href="https://soundcloud.com/jojotodos/giovanni-an-impossible-summer-2024-11" title="Giovanni - An Impossible Summer" target="_blank" style="color: #cccccc; text-decoration: none;">Giovanni - An Impossible Summer</a></div>

<p>During a three months road trip through southern Italy, I discovered my own pseudonym DJ project. It features - not only but many - <em>vocal tracks</em>, some Italian, but also German and English ones (ABAY, Edoardo Bennato, Bilderbuch, Rino Gaetano); some modern Italian and British electronic gems (Dina Summer, Almamegretta, The Comet is Coming) as well as some classic 70’s vibes in both Italian and German language (Pino D’Angio, Hildegard Knef).</p>

<p>Thanks to the always friendly and chill staff at northern sicilian campsite <em>Lo Scoglio</em> for introducing me to “Almamegretta”, a Dub &amp; World music artist from Naples. Best served on a 35 degrees afternoon under the shade of their restaurant’s terrace. &lt;3. Further credits go to those Italians that decided this (DJ-) person’s name should rather be “Giovanni” than “Jojo” for better flow in their mother tongue. Some artists were in the driving playlist ever since of course (The Comet is Coming. Thanks P.W-L). And certainly the biggest thanks goes to my co-pilot, tune selector, best travel companion and wife Christl.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Why is there no music on this blog? After all it is about music tinkering and stuff! Well, you are right, there should be music and now there is.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.jojotodos.net/images/2024-11-11-no-music/01.jpg" /><media:content medium="image" url="https://blog.jojotodos.net/images/2024-11-11-no-music/01.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">J0J0’s Git Essentials</title><link href="https://blog.jojotodos.net/git-essentials/" rel="alternate" type="text/html" title="J0J0’s Git Essentials" /><published>2024-01-16T00:00:00+00:00</published><updated>2024-01-16T00:00:00+00:00</updated><id>https://blog.jojotodos.net/git-essentials</id><content type="html" xml:base="https://blog.jojotodos.net/git-essentials/"><![CDATA[<ul>
  <li><a href="#introduction">Introduction</a>
    <ul>
      <li><a href="#quick-guide">Quick Guide</a></li>
      <li><a href="#how-to-use-this-document">How to use this document</a></li>
      <li><a href="#clearing-up-some-myths">Clearing up some myths</a></li>
      <li><a href="#git-as-a-collaboration-tool">Git as a collaboration tool</a></li>
    </ul>
  </li>
  <li><a href="#prerequisites">Prerequisites</a></li>
  <li><a href="#commands-cheat-sheet-section">Commands cheat sheet section</a>
    <ul>
      <li><a href="#the-in-between-commands">The “in-between” commands</a></li>
      <li><a href="#saving-state-commands">Saving state commands</a></li>
      <li><a href="#changing-history-commands---basic">Changing history commands - Basic</a></li>
      <li><a href="#jumping-to-points-in-time">Jumping to “points in time”</a></li>
      <li><a href="#starting-a-git-repo">Starting a Git repo</a></li>
      <li><a href="#putting-things-aside">Putting things aside</a></li>
      <li><a href="#deleting-files">Deleting files</a></li>
      <li><a href="#removing-uncommited-changes">Removing uncommited changes</a></li>
      <li><a href="#getting-back-stuff">Getting back stuff</a></li>
      <li><a href="#working-with-git-servers">Working with Git servers</a></li>
    </ul>
  </li>
  <li><a href="#best-practice-and-theory-section">Best practice and theory section</a>
    <ul>
      <li><a href="#what-should-be-in-a-commit">What should be in a commit?</a></li>
      <li><a href="#what-should-be-in-a-commit-message">What should be in a commit message?</a></li>
      <li><a href="#the-importance-of-gitignore">The importance of <code class="language-plaintext highlighter-rouge">.gitignore</code></a></li>
      <li><a href="#removing-instead-of-commenting-out-lines">Removing instead of commenting out lines</a></li>
      <li><a href="#branches">Branches</a></li>
    </ul>
  </li>
  <li><a href="#example-use-cases">Example use-cases</a>
    <ul>
      <li><a href="#example-use-case-1---static-website">Example use-case 1 - Static Website</a></li>
      <li><a href="#example-use-case-2---react-app-from-scratch">Example use-case 2 - React app from scratch</a></li>
    </ul>
  </li>
  <li><a href="#appendix">Appendix</a>
    <ul>
      <li><a href="#unix-like-command-line-tools-and-shells">UNIX-like command line tools and shells</a></li>
      <li><a href="#git-bash-bash-and-zsh">git-bash, bash and zsh</a></li>
      <li><a href="#configuring-your-shell">Configuring your shell</a>
        <ul>
          <li><a href="#configuring-git-bash-during-its-setup">Configuring git-bash during its setup</a></li>
        </ul>
      </li>
      <li><a href="#recommendations-on-terminal-programs">Recommendations on terminal programs</a>
        <ul>
          <li><a href="#windows">Windows</a></li>
          <li><a href="#macos">macOS</a></li>
          <li><a href="#linux">Linux</a></li>
        </ul>
      </li>
      <li><a href="#vim-editor-life-jacket">VIM editor life jacket</a></li>
      <li><a href="#version-managers-and-virtual-environments">Version managers and virtual environments</a>
        <ul>
          <li><a href="#nvm">NVM</a></li>
          <li><a href="#pyenv">pyenv</a></li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

<h1 id="introduction">Introduction</h1>
<p>This is a <strong>cheat sheet</strong> and my personal <strong>best practice collection</strong> aimed at ongoing developers, DevOps engineers, sysadmins and anyone anyone with a bit of experience in <a href="https://git-scm.com/">Git</a> who wants to <em>really</em> get started. After roughly 10 years of using it myself and having successfully introduced quite a few fellow sysadmins and developers to it, I thought it’s time for a write-up.</p>

<table>
  <thead>
    <tr>
      <th> </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>This is not another Git beginner’s guide. There is loads of those out there. Use them if you are a complete beginner or re-read above’s paragraph to make sure this is for you :-)</strong></td>
    </tr>
  </tbody>
</table>

<p> </p>

<p>Basically this document lists Git commands including <code class="language-plaintext highlighter-rouge">--options</code> I personally find most helpful and wish I’d known when I first got in to contact with Git.</p>

<p>Close to the end of the document there is an <a href="#example-use-cases">examples section</a> that runs through possible real-life scenarios, putting some of the contents together into common workflows.</p>

<h2 id="quick-guide">Quick Guide</h2>
<p>If you have a rough idea of how Git works already, I recommend reading these chapters to get you going quickly:</p>

<ul>
  <li>The introductory chapters <a href="#introduction">Intro</a>, <a href="#how-to-use-this-document">How to use… </a>, <a href="#clearing-up-some-myths">Myths</a> and <a href="#git-as-a-collaboration-tool">Git as a collaboration tool</a>.</li>
  <li>Then dive directly into <a href="#example-use-cases">The examples section</a>.</li>
</ul>

<p>Use the rest of the chapters as a reference and cheat sheet only!</p>

<p>Following that, I recommend proceeding to the <a href="#best-practice-and-theory-section">Best practice and theory section</a>.</p>

<h2 id="how-to-use-this-document">How to use this document</h2>
<p>Don’t feel overwhelmed by the amount of commands in this document, as often I’m presenting several possible ways of achieving the same. Pick and remember those you feel the most comfortable with.</p>

<p>Use these listings as a cheat sheet only. Type the commands into your terminal each time, rather than copying/pasting, and you will soon have learned them by heart.</p>

<p>There is dozen’s of Git how-tos out there, Git is super-powerful, nobody knows everything about it. This document tries to be practical and give some workflow ideas already without getting into too much detail on all the possibilities.</p>

<p><strong>Make using Git a habit!</strong> Creating habits for most humans at first feels like a burden but once it is established each execution feels like an achievement.</p>

<p>I promise Git will be a life-safer, your second brain and a tremendous help even for the tiniest of projects.</p>

<h2 id="clearing-up-some-myths">Clearing up some myths</h2>

<p>Git is <strong>offline first</strong>! Despite of common misbelieve, Git does not require any server part!</p>

<p>Git is not simply an upload tool for GitHub, Gitlab, Gitea or any other public or private Git backend system. It can certainly be used for for that but it’s not its main purpose.</p>

<p>Git is a “versioning” or “version control” tool. That does not literally mean it’s ment to create “release versions” of a program. It can certainly help with that but it’s not its sole purpose. A more descriptive name for tools like Git is “revision control”. If desired read the wikipedia entry about <a href="https://en.wikipedia.org/wiki/Version_control">version control</a>.</p>

<p>Git not only helps to save your code, it is a documentation tool as well. Whenever you go back to a previous project to look up something “you know you must have done” but don’t recall the details, you’ll be happy to find a description in your own words as well as an isolated version of “the changes required” to achieve it. Looking up things in horribly huge programs will be a thing of the past!</p>

<p>No coding project is too small to be put into a Git repo!</p>

<h2 id="git-as-a-collaboration-tool">Git as a collaboration tool</h2>
<p><em>The main goal of this document is to give a starting point for <strong>personal  coding projects</strong>.</em></p>

<p><em>When working in <strong>teams</strong> though, it’s all about <strong>common team rules</strong>. Some of the things in this document might be opinionated but I strongly believe that every developer/team member should at least know these basics, to successfully collaborate.</em></p>

<h1 id="prerequisites">Prerequisites</h1>
<ul>
  <li>A working Git installation on Windows, macOs or Linux.</li>
  <li>A basic understanding of UNIX-like command line tools.</li>
  <li>A basic understanding of what a shell is, which one you are using and how you configure the editor being used for text editing.</li>
</ul>

<p>Check out the <a href="#appendix">appendix chapters</a> if you’re not savvy with any of the above.</p>

<h1 id="commands-cheat-sheet-section">Commands cheat sheet section</h1>
<h2 id="the-in-between-commands">The “in-between” commands</h2>
<p>or  <strong>The “staying informed” commands</strong> or simply <strong>The “looking around” commands</strong></p>

<p>You use them all the time: Before <em>committing</em>, after <em>commiting</em>, whenever you get back to work, when you are not sure about the state of your repo, …</p>

<p><em><strong>As a rule of thumb, before you do anything with Git, use them!</strong></em></p>

<p><em><strong>They all are read-only and can be issued safely any time.</strong></em></p>

<table>
  <thead>
    <tr>
      <th> </th>
      <th> </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git status</code></td>
      <td>Displays files with <em>uncommited</em> changes, <em>untracked</em> files and gives hints in what state Git is in general. <strong>Your most important git command!</strong></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git log</code></td>
      <td>The history. Displays the list of commits including all the details.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git log --oneline</code></td>
      <td>A brief variant of the history.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git show &lt;hash&gt;</code></td>
      <td>Displays the <em>diff</em>(erence) of one commit to its previous one. In short, <strong>it displays a commit</strong> referenced by its commit-hash. Omit <code class="language-plaintext highlighter-rouge">&lt;hash&gt;</code> to see the last commit (the top-most in the history)</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git diff</code></td>
      <td>Show the <em>diff</em> between <em>uncommited</em> changes and the last commit (the top-most in the history).</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git diff &lt;hash1&gt; &lt;hash2&gt;</code></td>
      <td>Show the <em>diff</em> between the two commits</td>
    </tr>
  </tbody>
</table>

<p><em>Hint: The Commit-hashes you see in <code class="language-plaintext highlighter-rouge">git log</code> are pretty longish, but they can be abbreviated to a certain amount. If you look at <code class="language-plaintext highlighter-rouge">git log --oneline</code> you see about the maximum a hash can be abbreviated. Just try it out by looking at <code class="language-plaintext highlighter-rouge">git log</code> and then marking and copying only a part of the hash you see, starting from the left. Use that hash in another command, for example <code class="language-plaintext highlighter-rouge">git show abcdef123456</code>. It should work!</em></p>

<h2 id="saving-state-commands">Saving state commands</h2>
<p>Coming to Git’s main purpose: Tracking changes in files. The “chunks” we save those changes in, Git calls commits.</p>

<p><em>My personal rule of thumb and number 1 recommendation to any Git-non-experts: <strong>Never</strong> commit without double checking <strong>what</strong> will be committed with <code class="language-plaintext highlighter-rouge">git diff</code> and <code class="language-plaintext highlighter-rouge">git status</code>. Make it a habit!</em></p>

<table>
  <thead>
    <tr>
      <th> </th>
      <th> </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git add &lt;filename&gt;</code></td>
      <td>Hand over a file into Git’s control. It will be added with the <em>next</em> commit. We call this “staging for a commit”</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git add .</code></td>
      <td>Hand over <strong>all files</strong> in the directory into Git’s control. It will be added with the <em>next</em> commit.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git commit</code></td>
      <td>Finally record all staged changes into a new commit. You’ll be prompted to write a description - <strong><em>The Commit Message</em></strong>.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git commit -m "Sentence"</code></td>
      <td>Finally record all staged changes into a new commit. You pass the description on the command line already.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git commit -a</code></td>
      <td>A combination of “staging” and “commiting”: All changes in files known to Git will be staged and commited. You’ll be asked for a description.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git commit -a -m "Sentence"</code></td>
      <td>The same as above, providing the commit message on the command line already.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git commit -v</code></td>
      <td>My personal favorite: Comitting all staged changes. The editor prompting to input the description will <strong>additionally</strong> show <strong>the diff</strong> of your change. This helps to describe your changes right within the editor!</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git commit -v -a</code></td>
      <td>The same as above but do it for all changes in all files known to Git!</td>
    </tr>
  </tbody>
</table>

<p><em>Hint: After staging (<code class="language-plaintext highlighter-rouge">git add</code>ing) something for a commit, <code class="language-plaintext highlighter-rouge">git status</code> tells you that it’s staged (green). If you change a file (again) _after</em> that, you have to <strong>stage that file again</strong> (use <code class="language-plaintext highlighter-rouge">git add </code> again)! <code class="language-plaintext highlighter-rouge">git status</code> will tell you that, so always use it before finally <em>committing</em>!_</p>

<p><em>Hint: Commit often! Don’t make the beginners mistake of finishing the program, then doing one commit, just so you can upload it to GitHub!</em></p>

<h2 id="changing-history-commands---basic">Changing history commands - Basic</h2>
<p>If a commit is done it can still be changed, you can “amend” to it. The order of commits can also be changed (but that’s not demonstrated here).</p>

<p><em>Note (generalizing): Changing history is perfectly fine in personal projects but needs to be thought through carefully when working in teams. Don’t worry about it for now and use below commands often to fix/improve your existing commits</em></p>

<table>
  <thead>
    <tr>
      <th> </th>
      <th> </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git commit --amend</code></td>
      <td>Add all staged changes to the last commit (and be prompted for commit message changes). If no staged changes are present, this simply is <strong>the command to correct your commit message!</strong></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git commit -a --amend</code></td>
      <td>Add <strong>all changes in all files</strong> to last commit</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git commit -a -v --amend</code></td>
      <td>My personal favorite: Add <strong>all changes in all files</strong> to last commit, adapt <strong>commit message</strong>, while additionally <strong>showing the <em>diff</em></strong> of all those changes within the commit message editor. <em>This is an immensive help when writing commit messages!</em></td>
    </tr>
  </tbody>
</table>

<h2 id="jumping-to-points-in-time">Jumping to “points in time”</h2>
<p>To change the current state of a repo you can jump to any commit referencing it by its <em>commit-hash</em>. A commit can also have a “human readable” name, that is called a <em>branch</em>. The default branch Git creates for you is called <code class="language-plaintext highlighter-rouge">main</code> (or <code class="language-plaintext highlighter-rouge">master</code> in older Git versions).</p>

<table>
  <thead>
    <tr>
      <th> </th>
      <th> </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git checkout &lt;hash&gt;</code></td>
      <td>Set the repo to the state of that commit</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git checkout main</code></td>
      <td>Set the repo back to the state of the branch named <code class="language-plaintext highlighter-rouge">main</code> (essentially this <strong>usually</strong> is the command to return to the most recent commit.)</td>
    </tr>
  </tbody>
</table>

<h2 id="starting-a-git-repo">Starting a Git repo</h2>
<p>Any directory, no matter if entirely empty or populated with files already can be translated into a Git repo.</p>

<table>
  <thead>
    <tr>
      <th> </th>
      <th> </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git init</code></td>
      <td>Initialize the current directory as a Git repo (essentially creating a hidden subdirectory called <code class="language-plaintext highlighter-rouge">.git</code>)</td>
    </tr>
  </tbody>
</table>

<p><em>Hint: Typical steps after <code class="language-plaintext highlighter-rouge">git init</code> are creating and committing a <code class="language-plaintext highlighter-rouge">.gitignore</code> file, and adding and committing all files you might already have (<code class="language-plaintext highlighter-rouge">git add .; git commit</code>)</em></p>

<h2 id="putting-things-aside">Putting things aside</h2>
<p>Sometimes you’d want to “move aside” your current, uncommited changes (without commiting them) to do something else with git that requires it.</p>

<table>
  <thead>
    <tr>
      <th> </th>
      <th> </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git stash</code></td>
      <td>Move aside all unstaged changes onto the <em>stash stack</em></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git stash pop</code></td>
      <td>Get back the top-most entry from the <em>stash stack</em></td>
    </tr>
  </tbody>
</table>

<p><em>Hint: One use-case of <code class="language-plaintext highlighter-rouge">stash</code> is whenever you forgot something in your last commit and had started to work *on the next thing* already (i.e. changed code already): <code class="language-plaintext highlighter-rouge">git stash</code> all those changes. Fix what you forgot and <code class="language-plaintext highlighter-rouge">git commit -a --amend</code>  to your previous commit. Get back your changes with <code class="language-plaintext highlighter-rouge">git stash pop</code> and move on.</em></p>

<h2 id="deleting-files">Deleting files</h2>

<table>
  <thead>
    <tr>
      <th> </th>
      <th> </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git rm &lt;filename&gt;</code></td>
      <td>Delete a file and <strong>additionally</strong> stage that change for the next commit</td>
    </tr>
  </tbody>
</table>

<p><em>Hint: Deleting with regular operating system methods (File browser, <code class="language-plaintext highlighter-rouge">rm</code> command) is certainly also possible. You’d have to stage that change with <code class="language-plaintext highlighter-rouge">git add &lt;filename&gt;</code> in that case. <code class="language-plaintext highlighter-rouge">git rm</code>. spares you that step</em></p>

<p><em>Hint: Keeping deletions in separate commits, makes it easy to restore those files later on.</em></p>

<h2 id="removing-uncommited-changes">Removing uncommited changes</h2>
<p>Sometimes you experimented with something which doesn’t work anyway, want to get rid of it and start from a “known good” state.</p>

<table>
  <thead>
    <tr>
      <th> </th>
      <th> </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git reset --hard HEAD</code></td>
      <td>Delete all uncommited changes and reset the repo the state of the previous/the top-most commit. <code class="language-plaintext highlighter-rouge">HEAD</code> references the <em>top-most commit</em>!</td>
    </tr>
  </tbody>
</table>

<p><em>Hint: Instead of <code class="language-plaintext highlighter-rouge">HEAD</code> any commit-hash or branch-name can be used to set back the repo to exactly that state!</em></p>

<h2 id="getting-back-stuff">Getting back stuff</h2>
<p>Any change you ever recorded with Git can be restored, even entire file deletions!</p>

<p>Lookup the change you want to retrieve with <code class="language-plaintext highlighter-rouge">git log</code> (read your commit messages) and display the details (the actual changes) of a commit with <code class="language-plaintext highlighter-rouge">git show &lt;commit-hash&gt;</code>. If you found what you were looking for, use below’s checkout command to get that file’s change back.</p>

<table>
  <thead>
    <tr>
      <th> </th>
      <th> </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git checkout &lt;commit-hash&gt; &lt;filename&gt;</code></td>
      <td>Get back the state of the file as it was in the specified commit. You will get it as <em>staged</em> changes already. Use <code class="language-plaintext highlighter-rouge">git status</code> and <code class="language-plaintext highlighter-rouge">git diff --staged</code> to see them.</td>
    </tr>
  </tbody>
</table>

<p><em>Hint: Usually if you find the commit that _removed</em> something (a line or even an entire file), you would want to <code class="language-plaintext highlighter-rouge">checkout</code> from the commit <strong>before</strong> that, because it <strong>still has</strong> that required data present (Your recorded <strong>the deletion</strong> back then, thus want to restore from the state right before that operation!)_</p>

<h2 id="working-with-git-servers">Working with Git servers</h2>
<p>A local Git repo can be connected to another Git repo hosted on a server. Git calls those adresses <em>remotes</em>. A Git repo can be connected to <strong>one or multiple</strong> <em>remotes</em>.</p>

<table>
  <thead>
    <tr>
      <th> </th>
      <th> </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git remote -v</code></td>
      <td>Display all remotes</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git remote add myrepo https://github.com/username/reponame.git</code></td>
      <td>Connects the local Git repo to the remote repo hosted on GitHub and naming the remote  <code class="language-plaintext highlighter-rouge">myrepo</code></td>
    </tr>
  </tbody>
</table>

<p>When a repo is existing on a server already, it can be <em>cloned</em>, which creates a local copy of that repo into a subdirectory including a <em>remote</em> entry already.</p>

<table>
  <thead>
    <tr>
      <th> </th>
      <th> </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git clone https://github.com/username/reponame.git myrepo</code></td>
      <td>Clone the repo into the local directory <code class="language-plaintext highlighter-rouge">myrepo</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git clone https://github.com/username/reponame.git</code></td>
      <td>Clone the repo into the local directory <code class="language-plaintext highlighter-rouge">reponame</code> (automatically picks the remote repo’s name for the foldername)</td>
    </tr>
  </tbody>
</table>

<p>As long as proper remote entries are available, data can be transferred to servers, as well as retrieved from them. Assuming there is only one <em>remote</em> configured, use:</p>

<table>
  <thead>
    <tr>
      <th> </th>
      <th> </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git push</code></td>
      <td>Send to the <em>remote</em></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git pull</code></td>
      <td>Retrieve from <em>remote</em></td>
    </tr>
  </tbody>
</table>

<p>When collaborating on the same repository, Git needs to handle scenarios where others may have pushed changes to the server while you worked on your offline copy. If you attempt to push your latest commits, Git will prevent it. Instead, you must first pull down those changes, integrate them locally, and then proceed with pushing your changes. The command best suited for this task is:</p>

<table>
  <thead>
    <tr>
      <th> </th>
      <th> </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">git pull --rebase</code></td>
      <td>Move local changes aside, retrieve new commits from <em>remote</em>, integrate them into local copy, and put your previous local changes on top of it again. Now Git will allow sending your changes with <code class="language-plaintext highlighter-rouge">git push</code>.</td>
    </tr>
  </tbody>
</table>

<p><em>Since this document’s main focus is not about Git as a collaboration tool, you shouldn’t worry too much about this last concept for now. You’ll get guidance from your team colleauges in the future.</em></p>

<p><em>Hint: There is one reason though this concept might come in handy for you: If you happen to work on the same Git repo yourself from different computers!</em></p>

<h1 id="best-practice-and-theory-section">Best practice and theory section</h1>
<h2 id="what-should-be-in-a-commit">What should be in a commit?</h2>
<p>One of the things people struggle most with when starting out with Git is deciding what and when to commit…</p>

<ul>
  <li>A commit combines changes in the code that make sense together, examples for that are:
    <ul>
      <li>A bug is fixed</li>
      <li>A functionality was added / A feature was added</li>
      <li>A function was refactored</li>
    </ul>
  </li>
  <li>The reality is, you will make the beginners mistake of throwing too much into a commit! Don’t worry about it, you’ll learn to judge what belongs together, but be aware of the reasons why smaller commits are preferable:
    <ul>
      <li>Whenever you look at a commit’s change later on, it is always easier to read a “tiny change” in isolation than dozens of changed lines. You get the point!</li>
      <li>Later on in your career you’ll learn to combine several smaller commits into one bigger commit. Start small! Combining to bigger is <strong>easily</strong> possible, <strong>but not the other way round!</strong></li>
    </ul>
  </li>
</ul>

<h2 id="what-should-be-in-a-commit-message">What should be in a commit message?</h2>
<p>Writing good commit messages is on one hand an art form itself and on the other: Something a developing team needs to work out and agree on and if working alone, totally up to you!</p>

<p>I’ve read dozens of articles about writing commit messages but this one rule is sticking with me ever since and I found it most useful:</p>

<ul>
  <li>Use the present tense or use the imperative form!</li>
  <li>Don’t use the past tense!</li>
  <li>A sentence formed as follows should make sense: <strong><em>If this commit is applied, it will “your commit message”</em></strong></li>
</ul>

<p>So for example, your commit message could be: <code class="language-plaintext highlighter-rouge">Sort entries by date on user accounts page</code>, thus that sentence wouldn’t be perfect english but it would make sense: <strong><em>If this commit is applied, it will sort entries by ID on user accounts page.</em></strong></p>

<ul>
  <li>The maximum character length of the first line of a commit message (50 chars) should be respected! (You see it in <code class="language-plaintext highlighter-rouge">git log --oneline</code>)</li>
  <li>Feel free to elaborate in the rest of the commit message. Better more descriptive than not! Long commit messages don’t hurt anyone!</li>
</ul>

<p>A proper commit message could look like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Sort entries by ID on user accounts page

- By using the built-in sort method for arrays before passing it
  to the Table component.
- FIXME remember to fix the leading-zero problem later on!
</code></pre></div></div>

<p>I recommend <a href="https://www.freecodecamp.org/news/how-to-write-better-git-commit-messages/">this article on freecodecamp</a> if you want to further improve your commit message skills.</p>

<h2 id="the-importance-of-gitignore">The importance of <code class="language-plaintext highlighter-rouge">.gitignore</code></h2>
<p>Seldomly you’d want each and every file in your project repo to be tracked by Git. It makes sense to generally hide some files from it.</p>

<p>A <code class="language-plaintext highlighter-rouge">.gitignore</code> file resides in the root of the repo and has a very simple syntax. Each line represents a filename or <em>part</em> of a filename. Attaching <code class="language-plaintext highlighter-rouge">/</code> ensures matching a directory.</p>

<p><strong>Keeping <code class="language-plaintext highlighter-rouge">.gitignore</code> changes in their <em>own</em> commits and not mixing with actual <em>code</em> commits is a good practice.</strong></p>

<p>Examples for files you <em>usually</em> do not want to be commited <strong>ever</strong> are:</p>

<ul>
  <li>Configuration files of editors (<code class="language-plaintext highlighter-rouge">.vscode/</code>)</li>
  <li>Installed packages (<code class="language-plaintext highlighter-rouge">node_modules/</code>)</li>
  <li>Metadata cache files of operating systems and file browsers (<code class="language-plaintext highlighter-rouge">.DS_Store</code>, <code class="language-plaintext highlighter-rouge">Thumbs.db</code>)</li>
  <li>Directories holding final “builds” of your program (<code class="language-plaintext highlighter-rouge">.dist/</code>, <code class="language-plaintext highlighter-rouge">.build/</code>)</li>
  <li>Any temporary or cache files and directories (<code class="language-plaintext highlighter-rouge">.cache</code>, <code class="language-plaintext highlighter-rouge">.tmp</code>)</li>
  <li>Any other files you keep directly in your repo directory because you like to have them handy (documentation, code templates, CSS templates, …).</li>
</ul>

<p>A <code class="language-plaintext highlighter-rouge">.gitignore</code> file for a JavaScript project could look like this:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>.DS_Store
.vscode/
.cache
node_modules/
build/
dist/
requirements_checklists_for_this_project/
</code></pre></div></div>

<p><em>Hint: Some tools/toolchains bring their own <code class="language-plaintext highlighter-rouge">.gitignore</code> template already, for example projects created with <code class="language-plaintext highlighter-rouge">vite.js</code>, or <code class="language-plaintext highlighter-rouge">npx create-react-app</code>. Use those provided <code class="language-plaintext highlighter-rouge">.gitignore</code> files, commit them separately and add to them if required during the course of your project.</em></p>

<p><em>Hint: GitHub lets you select from a list of <code class="language-plaintext highlighter-rouge">.gitignore</code> templates when creating a fresh repo.</em></p>

<p><em>Hint: GitHub saves their collection of templates <a href="https://github.com/github/gitignore/blob/main/Node.gitignore">in a public repo</a>. For example <a href="https://github.com/github/gitignore/blob/main/Node.gitignore">this is their JavaScript/Node template</a>, you can copy/paste to your existing project!</em></p>

<h2 id="removing-instead-of-commenting-out-lines">Removing instead of commenting out lines</h2>
<p>Beginning developers tend to comment out a lot of stuff they are not sure about, want to keep it for reference and the likes. That basically is a good thing but there is a better way: Learn to read <em>diffs</em> and how to get those changes back!</p>

<p>So instead of putting a comment mark in front of a line (<code class="language-plaintext highlighter-rouge">#</code>, <code class="language-plaintext highlighter-rouge">//</code>, …), simply delete it. Keeping such a change (the deletion) in a separate commit with a descriptive commit message, allows for easy retrieval later on. Often the purpose of “commenting out” is because of “keeping it for reference”.</p>

<p>So for example we deleted a line from a CSS file and recorded that change in a separate commit, we can easily look it up later on with <code class="language-plaintext highlighter-rouge">git show &lt;commit-hash&gt;</code>:</p>

<div class="language-diff highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">commit 27399aedf2c6f4295b80e42ad2970006f9317bde (HEAD -&gt; main)
Author: J0J0 Todos &lt;jojo@peek-a-boo.at&gt;
Date:   Thu Jan 18 11:28:38 2024 +0100
</span>
    Delete border-bottom style of .nav-link.active CSS class

diff --git a/styles.css b/styles.css
<span class="gh">index 023332d..b8f2c91 100644
</span><span class="gd">--- a/styles.css
</span><span class="gi">+++ b/styles.css
</span><span class="p">@@ -52,7 +52,6 @@</span> hr {

 .nav-link.active {
   color: rgba(var(--dark_800), 1);
<span class="gd">-  border-bottom: 1px solid;
</span> }
</code></pre></div></div>

<p><em>Hint: Git remembers everything for you! Use this valuable feature!</em></p>

<p><em>Hint: Looking at diffs might be confusing at first. Get accustomed to it, it is an essential skill for any striving developer.</em></p>

<p><em>Hint: In most default terminal configurations diffs are presented in colors already. A tremendeous help for reading them. If that’s not the case, research how to fix your shell’s configuration!</em></p>

<h2 id="branches">Branches</h2>
<p>Branches mostly come in when working in teams and thus are not a focus in this write-up. A very basic understanding for them would be if you think of a branch as a “human readable name” for a specific commit which additionally allows to stack further commits on top of it.</p>

<p><strong>For now it is sufficient if you stick with the idea that a branch simply is a “human readable name” for a <em>commit hash</em>.</strong></p>

<h1 id="example-use-cases">Example use-cases</h1>
<p>In this chapter you’ll find some recipies for real-life scenarios putting to use some of the above commands and concepts.</p>
<h2 id="example-use-case-1---static-website">Example use-case 1 - Static Website</h2>
<p>You have a directory containing a static website project already. You have files named <code class="language-plaintext highlighter-rouge">index.html</code>, <code class="language-plaintext highlighter-rouge">styles.css</code>, <code class="language-plaintext highlighter-rouge">scripts.js</code>. You plan to use some more JavaScript in the project and might install some packages from <code class="language-plaintext highlighter-rouge">npm</code> soon.</p>

<p>You <code class="language-plaintext highlighter-rouge">cd</code> into the directory and run <code class="language-plaintext highlighter-rouge">git init</code>.</p>

<p>To make sure Git never commits some things, you create a file <code class="language-plaintext highlighter-rouge">.gitignore</code> in the directory containing the following:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>.vscode
node_modules
</code></pre></div></div>

<p>You <em>add</em> and <em>commit</em>:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git add .gitignore
git commit <span class="nt">-m</span> <span class="s2">"Initial commit, adding .gitignore"</span>
</code></pre></div></div>

<p>You realize that you want to elaborate on your commit message, so you call:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git commit <span class="nt">--amend</span>
</code></pre></div></div>

<p>You extend your commit message to be:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Initial commit, adding .gitignore

to make sure the vscode config <span class="nb">dir </span>and any installed node modules won<span class="s1">'t ever
be committed to Git.
</span></code></pre></div></div>

<p>In a second commit you want to add what you already had coded in your html, css and js files. You first inform yourself which files git sees as “untracked files” by issuing <code class="language-plaintext highlighter-rouge">git status</code>. You see your three files as “untracked” and decide you want to add them all together in one commit:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git add <span class="nb">.</span>
git commit <span class="nt">-v</span>
</code></pre></div></div>
<p>You get presented an editor that prompts you for the commit message and additionally displays the contents of your files (-v option), which helps you to find the right words for your message. You describe what you roughly had coded so far:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Basic structure of the project

The following features are working so far:

- ...
- ...
- ...
</code></pre></div></div>

<p>You save and quit the editor and have a look at your history with <code class="language-plaintext highlighter-rouge">git log</code>. You see your two commits and think it’s enough for the day.</p>

<p>The next day you come back to your project, you decide you want to use the <code class="language-plaintext highlighter-rouge">axios</code> JavaScript package. You install it with <code class="language-plaintext highlighter-rouge">npm install axios</code> and then check with <code class="language-plaintext highlighter-rouge">git status</code> which new files/dirs Git now sees as “untracked”. It shows two files named <code class="language-plaintext highlighter-rouge">package.json</code> and <code class="language-plaintext highlighter-rouge">package-lock.json</code>. The <code class="language-plaintext highlighter-rouge">node_modules</code> directory (that <code class="language-plaintext highlighter-rouge">npm</code> just created) is not being shown since yesterday you made sure it will be ignored already. You commit those two files:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git add package.json package-lock.json
git commit <span class="nt">-m</span> <span class="s2">"Add npm package files after installing axios"</span>
</code></pre></div></div>

<p>You make sure with <code class="language-plaintext highlighter-rouge">git status</code> that there are no “untracked” files and open changes.</p>

<p>You start working on your project’s html, js and css files and after some time have a navigation bar working that required changes in all three files. You display the changes with <code class="language-plaintext highlighter-rouge">git diff</code>, skim quickly through the <em>diff</em> to remind yourself what roughly you had coded and then commit them with:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git commit <span class="nt">-a</span> <span class="nt">-v</span>
</code></pre></div></div>

<p>You elaborate in the editor being presented what new features are working.</p>

<h2 id="example-use-case-2---react-app-from-scratch">Example use-case 2 - React app from scratch</h2>
<p>You create a new React app using <code class="language-plaintext highlighter-rouge">npx create-react-app myapp</code>.</p>

<p>You <code class="language-plaintext highlighter-rouge">cd</code> into the <code class="language-plaintext highlighter-rouge">myapp</code> directory and run <code class="language-plaintext highlighter-rouge">git status</code>. You realize that <code class="language-plaintext highlighter-rouge">create-react-app</code> already initialized the directory as a git repo. You don’t have to issu <code class="language-plaintext highlighter-rouge">git init</code>.</p>

<p><code class="language-plaintext highlighter-rouge">git status</code> also tells you <code class="language-plaintext highlighter-rouge">nothing to commit, working tree clean</code>, which seems odd but after issuing <code class="language-plaintext highlighter-rouge">git log</code> you understand what’s going on: <code class="language-plaintext highlighter-rouge">create-react-app</code> already did an initial commit for you. It looks like this:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>commit ff28dc2bb2b0f40d625e790fbdaf7895041232ec <span class="o">(</span>HEAD -&gt; main<span class="o">)</span>
Author: J0J0 Todos &lt;jojo@peek-a-boo.at&gt;
Date:   Thu Jan 18 14:06:47 2024 +0100

    Initialize project using Create React App
</code></pre></div></div>

<p>You type <code class="language-plaintext highlighter-rouge">git show</code> to view that commit. You skim through the changes quickly, see that <code class="language-plaintext highlighter-rouge">.gitignore</code> already lists a lot of stuff, so it seems you don’t need have to bother about that anymore. You find a default <code class="language-plaintext highlighter-rouge">README.md</code> provided you would probably want to adapt later on. All the source code of the example app seems to reside below a <code class="language-plaintext highlighter-rouge">src/</code> directory.</p>

<p>You start by deleting stuff you most probably won’t use right now. You’d like to record these deletions in an orderly fashion, to have a way to look up how it was done later on.</p>

<p>You <em>stage</em> the deletion of the logo with <code class="language-plaintext highlighter-rouge">git rm src/logo.svc</code> as a first step. You check with <code class="language-plaintext highlighter-rouge">git status</code>.</p>

<p>You remove all code that relates to that log file in the index.js</p>

<p><code class="language-plaintext highlighter-rouge">git diff</code> now tells you what exactly you had removed and you check visually if the change looks alright:</p>
<div class="language-diff highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gh">diff --git a/src/App.js b/src/App.js
index 3784575..e914079 100644
</span><span class="gd">--- a/src/App.js
</span><span class="gi">+++ b/src/App.js
</span><span class="p">@@ -1,11 +1,9 @@</span>
<span class="gd">-import logo from './logo.svg';
</span> import './App.css';

 function App() {
   return (
     &lt;div className="App"&gt;
       &lt;header className="App-header"&gt;
<span class="gd">-        &lt;img src={logo} className="App-logo" alt="logo" /&gt;
</span>         &lt;p&gt;
           Edit &lt;code&gt;src/App.js&lt;/code&gt; and save to reload.
         &lt;/p&gt;
<span class="p">@@ -22,4 +20,4 @@</span> function App() {
   );
 }
</code></pre></div></div>

<p>You see that the <code class="language-plaintext highlighter-rouge">import logo...</code> line will be removed and so will the line with the <code class="language-plaintext highlighter-rouge">&lt;img&gt;</code> tag. You have another look on the real App in the webbrowser and decide that it’s fine.</p>

<p>You <em>stage</em> all those changes and <em>commit</em> with:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git commit <span class="nt">-a</span> <span class="nt">-m</span> <span class="s2">"Remove default logo and all code referencing it"</span>
</code></pre></div></div>

<p>You convince yourself again that your deletions are recorded nicely, so you can look it up if you ever need it later. You issue <code class="language-plaintext highlighter-rouge">git show</code> and see that now you have everyhing together in one commit: The svg-logo-file deletion as well as the deletions of the relevant code lines (you saw a moment ago when checking with <code class="language-plaintext highlighter-rouge">git diff</code> prior to committing!)</p>

<p>As a final step you check <code class="language-plaintext highlighter-rouge">git log</code> and it looks like this:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>commit 61eacfab5213daa3685329976ed5a259a0fc15f4 <span class="o">(</span>HEAD -&gt; main<span class="o">)</span>
Author: J0J0 Todos &lt;jojo@peek-a-boo.at&gt;
Date:   Thu Jan 18 14:45:08 2024 +0100

    Remove default logo and all code referencing it

commit ff28dc2bb2b0f40d625e790fbdaf7895041232ec
Author: J0J0 Todos &lt;jojo@peek-a-boo.at&gt;
Date:   Thu Jan 18 14:06:47 2024 +0100

    Initialize project using Create React App
</code></pre></div></div>

<p>Whenever you would want to look up how that logo of the default App was implemented, you simply would issue <code class="language-plaintext highlighter-rouge">git show 61eacfab52</code>.</p>

<p>You do some more cleanup commits but decide that cleaning makes tired. It was an important first step but you need a break. You look forward to starting fresh with an already tidied up project repo after your break :-)</p>

<h1 id="appendix">Appendix</h1>
<p>Often beginning developers come from a mostly GUI oriented world of computers. These chapters should give the crashiest of crash courses to command line interfaces.</p>

<h2 id="unix-like-command-line-tools-and-shells">UNIX-like command line tools and shells</h2>
<p>UNIX-like commands typically follow a pattern with a <code class="language-plaintext highlighter-rouge">command</code> accepting options, often with long (<code class="language-plaintext highlighter-rouge">--something</code>) and abbreviated (<code class="language-plaintext highlighter-rouge">-s</code>) forms. Due to the limited alphabet, shortforms may not be intuitive, but you can find them using <code class="language-plaintext highlighter-rouge">--help</code> or <code class="language-plaintext highlighter-rouge">-h</code>.</p>

<p>A <em>shell</em>, very simply put, is a program that accepts interactive command inputs from a user. Two common ones are named <code class="language-plaintext highlighter-rouge">bash</code> and <code class="language-plaintext highlighter-rouge">zsh</code>.</p>

<p>A <em>shell</em> on a graphical operating system requires a <em>Terminal Emulator Program</em> to be run!</p>

<p>So to be exact, a <em>shell</em> is not a <em>Terminal</em>. A <em>Terminal</em> just runs a <em>shell</em> as the very first thing when launched.</p>

<h2 id="git-bash-bash-and-zsh">git-bash, bash and zsh</h2>
<p><code class="language-plaintext highlighter-rouge">git</code> is a UNIX-like command. I <em>suppose</em> because of its UNIX-like nature, things like <code class="language-plaintext highlighter-rouge">git-bash</code> were invented to adapt it for Windows (where command syntax actually follows a different pattern (eg. <code class="language-plaintext highlighter-rouge">/s</code> for an option instead of <code class="language-plaintext highlighter-rouge">-s</code>).</p>

<p><code class="language-plaintext highlighter-rouge">git-bash</code> is a Windows version of the widely-used <code class="language-plaintext highlighter-rouge">bash</code> shell known from Linux/BSD/macOS and other *NIX systems. It’s not directly related to the functionality of the <code class="language-plaintext highlighter-rouge">git</code> command itself.</p>

<p>Nowadays macOS and Linux often use <code class="language-plaintext highlighter-rouge">zsh</code> as the default shell, which in fact is a <code class="language-plaintext highlighter-rouge">bash</code>-compatible shell.</p>

<p>To find out which shell you are using, do</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">echo</span> <span class="nv">$SHELL</span>
</code></pre></div></div>
<p>If that points to something like this: <code class="language-plaintext highlighter-rouge">/bin/sh</code>, and you still are not sure, do</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sh <span class="nt">--version</span>
</code></pre></div></div>

<h2 id="configuring-your-shell">Configuring your shell</h2>
<p>To configure your shell, find and edit the <code class="language-plaintext highlighter-rouge">.zshrc</code> or <code class="language-plaintext highlighter-rouge">.bashrc</code> file in your <em>home directory</em>. <strong>If not existing, simply create it!</strong></p>

<p><em><code class="language-plaintext highlighter-rouge">git-bash</code> also uses <code class="language-plaintext highlighter-rouge">.bashrc</code>.</em></p>

<p><em>The <code class="language-plaintext highlighter-rouge">cd</code> command without any arguments always sends you “back home”. To find out where your homedirectory is located exactly, use <code class="language-plaintext highlighter-rouge">echo $HOME</code>)</em></p>

<p>Append a line to the config file of your shell, to modify the <code class="language-plaintext highlighter-rouge">EDITOR</code> environment variable, which <strong>sets the default editor</strong> for CLI tools like <code class="language-plaintext highlighter-rouge">git</code>. For example on Windows to use notepad:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">export </span><span class="nv">EDITOR</span><span class="o">=</span><span class="s2">"notepad"</span>
</code></pre></div></div>

<p>Restart the shell for changes to take effect (use the <code class="language-plaintext highlighter-rouge">exit</code> command). Verify the new setting with <code class="language-plaintext highlighter-rouge">echo $EDITOR</code>.</p>

<p><em>It helps to choose an editor that supports syntax highlighting, since Git can display source code within the editor while writing commit-messages. So on Windows you could use <code class="language-plaintext highlighter-rouge">notepad++</code> if you have it installed, or <code class="language-plaintext highlighter-rouge">nano</code>, which ships with git-bash, on macOS also try <code class="language-plaintext highlighter-rouge">nano</code>.</em></p>

<p><em>If for some reason setting <code class="language-plaintext highlighter-rouge">EDITOR</code> does not work, it could be that Git’s own config overrides it.</em></p>

<ul>
  <li><em><strong>Check</strong> with <code class="language-plaintext highlighter-rouge">git config --global --get core.editor</code></em></li>
  <li><em><strong>Set</strong> with <code class="language-plaintext highlighter-rouge">git config --global core.editor notepad</code></em></li>
</ul>

<h3 id="configuring-git-bash-during-its-setup">Configuring git-bash during its setup</h3>
<p>The git-bash installer asks a ton of questions, those are worth considering:</p>

<ul>
  <li><em>Select Components</em> - Activate <strong>“Add a Git Bash Profile to Windows Terminal”</strong></li>
  <li><em>Changing the default editor used by Git</em> - Best you leave this at default (vim), because only then you keep the possiblity to control it using the <code class="language-plaintext highlighter-rouge">EDITOR</code> shell environment variable. If you’ve had changed it.</li>
  <li><em>Configuring the terminal emulator to use with Git Bash</em> - Don’t set to “Use Windows default console window”, keep the default “Use minTTY”!</li>
</ul>

<p><em>Hint: To change settings after you’ve completed setup already, re-run the git-bash installation fiile.</em></p>

<h2 id="recommendations-on-terminal-programs">Recommendations on terminal programs</h2>
<h3 id="windows">Windows</h3>
<p>The git-bash installation, comes with it’s own terminal emulater named <a href="https://mintty.github.io/">minTTY</a>.</p>

<p>Microsofts “own” (but developed open-source) <a href="https://apps.microsoft.com/detail/9N0DX20HK701?hl=en-US&amp;gl=US">Windows Terminal</a> is a good alternative to minTTY.</p>

<p><em>Hint: To use <code class="language-plaintext highlighter-rouge">git-bash</code> as the <strong>default shell when opening a new Windows Terminal</strong> window, go to its Settings dialog -&gt; Startup -&gt; Default Profile, and select “Git Bash”</em></p>

<p><em>Hint: Copy marked text in Windows Terminal to the clipboard by using the Return key. Paste text into it with a “Right Click”.</em></p>

<h3 id="macos">macOS</h3>
<p>On macOS I find the default Terminal app lacking. My recommendation is the Open Source alternative <a href="https://iterm2.com/">iTerm</a>. It remembers the state of open terminals when your computer reboots (or even crashes), it supports “split panes” and offers loads of other handy features!</p>

<h3 id="linux">Linux</h3>
<p>For Linux, I personally was using <code class="language-plaintext highlighter-rouge">Terminator</code> for ages, but nowadays like <code class="language-plaintext highlighter-rouge">Konsole</code>. Both supporting “split panes”. Numerous excellent alternatives exist on any Linux distro.</p>

<h2 id="vim-editor-life-jacket">VIM editor life jacket</h2>
<p><code class="language-plaintext highlighter-rouge">vim</code> stands out as a super-powerful text editors that became famous with UNIX admins and programmers because of it’s wide spread availability on commercial *NIX systems as well as Linux and macOS. For those new to <code class="language-plaintext highlighter-rouge">vim</code>, its unconventional interface can be intimidating.</p>

<p>Here are some life saving concepts you need to know to at least write commit messages with it. If you don’t want to go down that rabbit hole, just reconfigure your shell to use your favorite editor as shown in the previous chapter.</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">vim</code> initiates in the <em>normal</em> mode, requiring commands for actions. Copy lines by moving over them and typing <code class="language-plaintext highlighter-rouge">yy</code>. Paste elsewhere with <code class="language-plaintext highlighter-rouge">p</code>. (just an example, so you get the idea!)</li>
  <li>To input characters, switch to <em>insert</em> mode using the <code class="language-plaintext highlighter-rouge">i</code> command.</li>
  <li>While in <em>insert</em> mode, edit as usual.</li>
  <li>Exit <em>insert</em> mode by pressing <code class="language-plaintext highlighter-rouge">Esc</code> (back to <em>normal</em> mode). There’s also an <em>ex</em> mode, accessed with <code class="language-plaintext highlighter-rouge">:</code>.</li>
  <li>Save the file with <code class="language-plaintext highlighter-rouge">:w</code>.</li>
  <li>Quit the file with <code class="language-plaintext highlighter-rouge">:q</code>.</li>
  <li>Save and quit simultaneously with <code class="language-plaintext highlighter-rouge">:wq</code>.</li>
</ul>

<p>Many might exclaim, “That is crazy!” Indeed, it might be, but the strength of <code class="language-plaintext highlighter-rouge">vim</code> lies in its design for complete mouse-less control. Mastering numerous shortcuts enables swift and efficient editing.</p>

<p>Anyway, choose your poison and HTH!</p>

<h2 id="version-managers-and-virtual-environments">Version managers and virtual environments</h2>
<p>A slightly off-topic chapter around the “dependency hell” new developers <em>will</em> face often. JavaScript programmers want to use <em>NVM</em>, Python programmers have several options, I recommend <em>pyenv</em>.</p>
<h3 id="nvm">NVM</h3>

<p>Allows changing the Node version during a shell session with simple commands. <a href="https://github.com/nvm-sh/nvm">Read the installation chapter in the official GitHub repo</a>.</p>

<p><code class="language-plaintext highlighter-rouge">nvm</code> usually is installed directly into the the user’s home directory into a hidden directory named <code class="language-plaintext highlighter-rouge">.nvm/</code>. A main concept of how it works is it’s simply writing a few lines to the user’s shell configuration (<code class="language-plaintext highlighter-rouge">.bashrc</code>, <code class="language-plaintext highlighter-rouge">.zshrc</code>). Details if interested in <a href="https://github.com/nvm-sh/nvm?tab=readme-ov-file#git-install">this section of its docs</a>.</p>

<p>For developing on Windows there’s <strong>another project existing</strong>. It’s <strong>unrelated</strong> to the original <code class="language-plaintext highlighter-rouge">nvm</code> project and follows an entirely different approach. <a href="https://github.com/coreybutler/nvm-windows">Get nvm-windows here</a></p>

<p><em>Hint: There is a caveat with nvm-windows when being used with git-bash: Due to its differnt nature (not configured via shell configuration files) it does not work when git-bash is run via minTTY (The original “Git Bash” entry in Start Menu!). You have to run git-bash via a Windows Terminal profile <a href="#windows">as described previously</a>.</em></p>

<h3 id="pyenv">pyenv</h3>

<p><code class="language-plaintext highlighter-rouge">pyenv</code> is my recommendation for creating self-contained virtual Python development environments without touching the “built-in” version of the OS. <a href="https://github.com/pyenv/pyenv?tab=readme-ov-file#what-pyenv-does">Learn what it does</a> and <a href="https://github.com/pyenv/pyenv?tab=readme-ov-file#installation">follow its excellent installation documentation</a>.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Introduction Quick Guide How to use this document Clearing up some myths Git as a collaboration tool Prerequisites Commands cheat sheet section The “in-between” commands Saving state commands Changing history commands - Basic Jumping to “points in time” Starting a Git repo Putting things aside Deleting files Removing uncommited changes Getting back stuff Working with Git servers Best practice and theory section What should be in a commit? What should be in a commit message? The importance of .gitignore Removing instead of commenting out lines Branches Example use-cases Example use-case 1 - Static Website Example use-case 2 - React app from scratch Appendix UNIX-like command line tools and shells git-bash, bash and zsh Configuring your shell Configuring git-bash during its setup Recommendations on terminal programs Windows macOS Linux VIM editor life jacket Version managers and virtual environments NVM pyenv Introduction This is a cheat sheet and my personal best practice collection aimed at ongoing developers, DevOps engineers, sysadmins and anyone anyone with a bit of experience in Git who wants to really get started. After roughly 10 years of using it myself and having successfully introduced quite a few fellow sysadmins and developers to it, I thought it’s time for a write-up.   This is not another Git beginner’s guide. There is loads of those out there. Use them if you are a complete beginner or re-read above’s paragraph to make sure this is for you :-)   Basically this document lists Git commands including --options I personally find most helpful and wish I’d known when I first got in to contact with Git. Close to the end of the document there is an examples section that runs through possible real-life scenarios, putting some of the contents together into common workflows. Quick Guide If you have a rough idea of how Git works already, I recommend reading these chapters to get you going quickly: The introductory chapters Intro, How to use… , Myths and Git as a collaboration tool. Then dive directly into The examples section. Use the rest of the chapters as a reference and cheat sheet only! Following that, I recommend proceeding to the Best practice and theory section. How to use this document Don’t feel overwhelmed by the amount of commands in this document, as often I’m presenting several possible ways of achieving the same. Pick and remember those you feel the most comfortable with. Use these listings as a cheat sheet only. Type the commands into your terminal each time, rather than copying/pasting, and you will soon have learned them by heart. There is dozen’s of Git how-tos out there, Git is super-powerful, nobody knows everything about it. This document tries to be practical and give some workflow ideas already without getting into too much detail on all the possibilities. Make using Git a habit! Creating habits for most humans at first feels like a burden but once it is established each execution feels like an achievement. I promise Git will be a life-safer, your second brain and a tremendous help even for the tiniest of projects. Clearing up some myths Git is offline first! Despite of common misbelieve, Git does not require any server part! Git is not simply an upload tool for GitHub, Gitlab, Gitea or any other public or private Git backend system. It can certainly be used for for that but it’s not its main purpose. Git is a “versioning” or “version control” tool. That does not literally mean it’s ment to create “release versions” of a program. It can certainly help with that but it’s not its sole purpose. A more descriptive name for tools like Git is “revision control”. If desired read the wikipedia entry about version control. Git not only helps to save your code, it is a documentation tool as well. Whenever you go back to a previous project to look up something “you know you must have done” but don’t recall the details, you’ll be happy to find a description in your own words as well as an isolated version of “the changes required” to achieve it. Looking up things in horribly huge programs will be a thing of the past! No coding project is too small to be put into a Git repo! Git as a collaboration tool The main goal of this document is to give a starting point for personal coding projects. When working in teams though, it’s all about common team rules. Some of the things in this document might be opinionated but I strongly believe that every developer/team member should at least know these basics, to successfully collaborate. Prerequisites A working Git installation on Windows, macOs or Linux. A basic understanding of UNIX-like command line tools. A basic understanding of what a shell is, which one you are using and how you configure the editor being used for text editing. Check out the appendix chapters if you’re not savvy with any of the above. Commands cheat sheet section The “in-between” commands or The “staying informed” commands or simply The “looking around” commands You use them all the time: Before committing, after commiting, whenever you get back to work, when you are not sure about the state of your repo, … As a rule of thumb, before you do anything with Git, use them! They all are read-only and can be issued safely any time.     git status Displays files with uncommited changes, untracked files and gives hints in what state Git is in general. Your most important git command! git log The history. Displays the list of commits including all the details. git log --oneline A brief variant of the history. git show &lt;hash&gt; Displays the diff(erence) of one commit to its previous one. In short, it displays a commit referenced by its commit-hash. Omit &lt;hash&gt; to see the last commit (the top-most in the history) git diff Show the diff between uncommited changes and the last commit (the top-most in the history). git diff &lt;hash1&gt; &lt;hash2&gt; Show the diff between the two commits Hint: The Commit-hashes you see in git log are pretty longish, but they can be abbreviated to a certain amount. If you look at git log --oneline you see about the maximum a hash can be abbreviated. Just try it out by looking at git log and then marking and copying only a part of the hash you see, starting from the left. Use that hash in another command, for example git show abcdef123456. It should work! Saving state commands Coming to Git’s main purpose: Tracking changes in files. The “chunks” we save those changes in, Git calls commits. My personal rule of thumb and number 1 recommendation to any Git-non-experts: Never commit without double checking what will be committed with git diff and git status. Make it a habit!     git add &lt;filename&gt; Hand over a file into Git’s control. It will be added with the next commit. We call this “staging for a commit” git add . Hand over all files in the directory into Git’s control. It will be added with the next commit. git commit Finally record all staged changes into a new commit. You’ll be prompted to write a description - The Commit Message. git commit -m "Sentence" Finally record all staged changes into a new commit. You pass the description on the command line already. git commit -a A combination of “staging” and “commiting”: All changes in files known to Git will be staged and commited. You’ll be asked for a description. git commit -a -m "Sentence" The same as above, providing the commit message on the command line already. git commit -v My personal favorite: Comitting all staged changes. The editor prompting to input the description will additionally show the diff of your change. This helps to describe your changes right within the editor! git commit -v -a The same as above but do it for all changes in all files known to Git! Hint: After staging (git adding) something for a commit, git status tells you that it’s staged (green). If you change a file (again) _after that, you have to stage that file again (use git add again)! git status will tell you that, so always use it before finally committing!_ Hint: Commit often! Don’t make the beginners mistake of finishing the program, then doing one commit, just so you can upload it to GitHub! Changing history commands - Basic If a commit is done it can still be changed, you can “amend” to it. The order of commits can also be changed (but that’s not demonstrated here). Note (generalizing): Changing history is perfectly fine in personal projects but needs to be thought through carefully when working in teams. Don’t worry about it for now and use below commands often to fix/improve your existing commits     git commit --amend Add all staged changes to the last commit (and be prompted for commit message changes). If no staged changes are present, this simply is the command to correct your commit message! git commit -a --amend Add all changes in all files to last commit git commit -a -v --amend My personal favorite: Add all changes in all files to last commit, adapt commit message, while additionally showing the diff of all those changes within the commit message editor. This is an immensive help when writing commit messages! Jumping to “points in time” To change the current state of a repo you can jump to any commit referencing it by its commit-hash. A commit can also have a “human readable” name, that is called a branch. The default branch Git creates for you is called main (or master in older Git versions).     git checkout &lt;hash&gt; Set the repo to the state of that commit git checkout main Set the repo back to the state of the branch named main (essentially this usually is the command to return to the most recent commit.) Starting a Git repo Any directory, no matter if entirely empty or populated with files already can be translated into a Git repo.     git init Initialize the current directory as a Git repo (essentially creating a hidden subdirectory called .git) Hint: Typical steps after git init are creating and committing a .gitignore file, and adding and committing all files you might already have (git add .; git commit) Putting things aside Sometimes you’d want to “move aside” your current, uncommited changes (without commiting them) to do something else with git that requires it.     git stash Move aside all unstaged changes onto the stash stack git stash pop Get back the top-most entry from the stash stack Hint: One use-case of stash is whenever you forgot something in your last commit and had started to work *on the next thing* already (i.e. changed code already): git stash all those changes. Fix what you forgot and git commit -a --amend to your previous commit. Get back your changes with git stash pop and move on. Deleting files     git rm &lt;filename&gt; Delete a file and additionally stage that change for the next commit Hint: Deleting with regular operating system methods (File browser, rm command) is certainly also possible. You’d have to stage that change with git add &lt;filename&gt; in that case. git rm. spares you that step Hint: Keeping deletions in separate commits, makes it easy to restore those files later on. Removing uncommited changes Sometimes you experimented with something which doesn’t work anyway, want to get rid of it and start from a “known good” state.     git reset --hard HEAD Delete all uncommited changes and reset the repo the state of the previous/the top-most commit. HEAD references the top-most commit! Hint: Instead of HEAD any commit-hash or branch-name can be used to set back the repo to exactly that state! Getting back stuff Any change you ever recorded with Git can be restored, even entire file deletions! Lookup the change you want to retrieve with git log (read your commit messages) and display the details (the actual changes) of a commit with git show &lt;commit-hash&gt;. If you found what you were looking for, use below’s checkout command to get that file’s change back.     git checkout &lt;commit-hash&gt; &lt;filename&gt; Get back the state of the file as it was in the specified commit. You will get it as staged changes already. Use git status and git diff --staged to see them. Hint: Usually if you find the commit that _removed something (a line or even an entire file), you would want to checkout from the commit before that, because it still has that required data present (Your recorded the deletion back then, thus want to restore from the state right before that operation!)_ Working with Git servers A local Git repo can be connected to another Git repo hosted on a server. Git calls those adresses remotes. A Git repo can be connected to one or multiple remotes.     git remote -v Display all remotes git remote add myrepo https://github.com/username/reponame.git Connects the local Git repo to the remote repo hosted on GitHub and naming the remote myrepo When a repo is existing on a server already, it can be cloned, which creates a local copy of that repo into a subdirectory including a remote entry already.     git clone https://github.com/username/reponame.git myrepo Clone the repo into the local directory myrepo git clone https://github.com/username/reponame.git Clone the repo into the local directory reponame (automatically picks the remote repo’s name for the foldername) As long as proper remote entries are available, data can be transferred to servers, as well as retrieved from them. Assuming there is only one remote configured, use:     git push Send to the remote git pull Retrieve from remote When collaborating on the same repository, Git needs to handle scenarios where others may have pushed changes to the server while you worked on your offline copy. If you attempt to push your latest commits, Git will prevent it. Instead, you must first pull down those changes, integrate them locally, and then proceed with pushing your changes. The command best suited for this task is:     git pull --rebase Move local changes aside, retrieve new commits from remote, integrate them into local copy, and put your previous local changes on top of it again. Now Git will allow sending your changes with git push. Since this document’s main focus is not about Git as a collaboration tool, you shouldn’t worry too much about this last concept for now. You’ll get guidance from your team colleauges in the future. Hint: There is one reason though this concept might come in handy for you: If you happen to work on the same Git repo yourself from different computers! Best practice and theory section What should be in a commit? One of the things people struggle most with when starting out with Git is deciding what and when to commit… A commit combines changes in the code that make sense together, examples for that are: A bug is fixed A functionality was added / A feature was added A function was refactored The reality is, you will make the beginners mistake of throwing too much into a commit! Don’t worry about it, you’ll learn to judge what belongs together, but be aware of the reasons why smaller commits are preferable: Whenever you look at a commit’s change later on, it is always easier to read a “tiny change” in isolation than dozens of changed lines. You get the point! Later on in your career you’ll learn to combine several smaller commits into one bigger commit. Start small! Combining to bigger is easily possible, but not the other way round! What should be in a commit message? Writing good commit messages is on one hand an art form itself and on the other: Something a developing team needs to work out and agree on and if working alone, totally up to you! I’ve read dozens of articles about writing commit messages but this one rule is sticking with me ever since and I found it most useful: Use the present tense or use the imperative form! Don’t use the past tense! A sentence formed as follows should make sense: If this commit is applied, it will “your commit message” So for example, your commit message could be: Sort entries by date on user accounts page, thus that sentence wouldn’t be perfect english but it would make sense: If this commit is applied, it will sort entries by ID on user accounts page. The maximum character length of the first line of a commit message (50 chars) should be respected! (You see it in git log --oneline) Feel free to elaborate in the rest of the commit message. Better more descriptive than not! Long commit messages don’t hurt anyone! A proper commit message could look like this: Sort entries by ID on user accounts page - By using the built-in sort method for arrays before passing it to the Table component. - FIXME remember to fix the leading-zero problem later on! I recommend this article on freecodecamp if you want to further improve your commit message skills. The importance of .gitignore Seldomly you’d want each and every file in your project repo to be tracked by Git. It makes sense to generally hide some files from it. A .gitignore file resides in the root of the repo and has a very simple syntax. Each line represents a filename or part of a filename. Attaching / ensures matching a directory. Keeping .gitignore changes in their own commits and not mixing with actual code commits is a good practice. Examples for files you usually do not want to be commited ever are: Configuration files of editors (.vscode/) Installed packages (node_modules/) Metadata cache files of operating systems and file browsers (.DS_Store, Thumbs.db) Directories holding final “builds” of your program (.dist/, .build/) Any temporary or cache files and directories (.cache, .tmp) Any other files you keep directly in your repo directory because you like to have them handy (documentation, code templates, CSS templates, …). A .gitignore file for a JavaScript project could look like this: .DS_Store .vscode/ .cache node_modules/ build/ dist/ requirements_checklists_for_this_project/ Hint: Some tools/toolchains bring their own .gitignore template already, for example projects created with vite.js, or npx create-react-app. Use those provided .gitignore files, commit them separately and add to them if required during the course of your project. Hint: GitHub lets you select from a list of .gitignore templates when creating a fresh repo. Hint: GitHub saves their collection of templates in a public repo. For example this is their JavaScript/Node template, you can copy/paste to your existing project! Removing instead of commenting out lines Beginning developers tend to comment out a lot of stuff they are not sure about, want to keep it for reference and the likes. That basically is a good thing but there is a better way: Learn to read diffs and how to get those changes back! So instead of putting a comment mark in front of a line (#, //, …), simply delete it. Keeping such a change (the deletion) in a separate commit with a descriptive commit message, allows for easy retrieval later on. Often the purpose of “commenting out” is because of “keeping it for reference”. So for example we deleted a line from a CSS file and recorded that change in a separate commit, we can easily look it up later on with git show &lt;commit-hash&gt;: commit 27399aedf2c6f4295b80e42ad2970006f9317bde (HEAD -&gt; main) Author: J0J0 Todos &lt;jojo@peek-a-boo.at&gt; Date: Thu Jan 18 11:28:38 2024 +0100 Delete border-bottom style of .nav-link.active CSS class diff --git a/styles.css b/styles.css index 023332d..b8f2c91 100644 --- a/styles.css +++ b/styles.css @@ -52,7 +52,6 @@ hr { .nav-link.active { color: rgba(var(--dark_800), 1); - border-bottom: 1px solid; } Hint: Git remembers everything for you! Use this valuable feature! Hint: Looking at diffs might be confusing at first. Get accustomed to it, it is an essential skill for any striving developer. Hint: In most default terminal configurations diffs are presented in colors already. A tremendeous help for reading them. If that’s not the case, research how to fix your shell’s configuration! Branches Branches mostly come in when working in teams and thus are not a focus in this write-up. A very basic understanding for them would be if you think of a branch as a “human readable name” for a specific commit which additionally allows to stack further commits on top of it. For now it is sufficient if you stick with the idea that a branch simply is a “human readable name” for a commit hash. Example use-cases In this chapter you’ll find some recipies for real-life scenarios putting to use some of the above commands and concepts. Example use-case 1 - Static Website You have a directory containing a static website project already. You have files named index.html, styles.css, scripts.js. You plan to use some more JavaScript in the project and might install some packages from npm soon. You cd into the directory and run git init. To make sure Git never commits some things, you create a file .gitignore in the directory containing the following: .vscode node_modules You add and commit: git add .gitignore git commit -m "Initial commit, adding .gitignore" You realize that you want to elaborate on your commit message, so you call: git commit --amend You extend your commit message to be: Initial commit, adding .gitignore to make sure the vscode config dir and any installed node modules won't ever be committed to Git. In a second commit you want to add what you already had coded in your html, css and js files. You first inform yourself which files git sees as “untracked files” by issuing git status. You see your three files as “untracked” and decide you want to add them all together in one commit: git add . git commit -v You get presented an editor that prompts you for the commit message and additionally displays the contents of your files (-v option), which helps you to find the right words for your message. You describe what you roughly had coded so far: Basic structure of the project The following features are working so far: - ... - ... - ... You save and quit the editor and have a look at your history with git log. You see your two commits and think it’s enough for the day. The next day you come back to your project, you decide you want to use the axios JavaScript package. You install it with npm install axios and then check with git status which new files/dirs Git now sees as “untracked”. It shows two files named package.json and package-lock.json. The node_modules directory (that npm just created) is not being shown since yesterday you made sure it will be ignored already. You commit those two files: git add package.json package-lock.json git commit -m "Add npm package files after installing axios" You make sure with git status that there are no “untracked” files and open changes. You start working on your project’s html, js and css files and after some time have a navigation bar working that required changes in all three files. You display the changes with git diff, skim quickly through the diff to remind yourself what roughly you had coded and then commit them with: git commit -a -v You elaborate in the editor being presented what new features are working. Example use-case 2 - React app from scratch You create a new React app using npx create-react-app myapp. You cd into the myapp directory and run git status. You realize that create-react-app already initialized the directory as a git repo. You don’t have to issu git init. git status also tells you nothing to commit, working tree clean, which seems odd but after issuing git log you understand what’s going on: create-react-app already did an initial commit for you. It looks like this: commit ff28dc2bb2b0f40d625e790fbdaf7895041232ec (HEAD -&gt; main) Author: J0J0 Todos &lt;jojo@peek-a-boo.at&gt; Date: Thu Jan 18 14:06:47 2024 +0100 Initialize project using Create React App You type git show to view that commit. You skim through the changes quickly, see that .gitignore already lists a lot of stuff, so it seems you don’t need have to bother about that anymore. You find a default README.md provided you would probably want to adapt later on. All the source code of the example app seems to reside below a src/ directory. You start by deleting stuff you most probably won’t use right now. You’d like to record these deletions in an orderly fashion, to have a way to look up how it was done later on. You stage the deletion of the logo with git rm src/logo.svc as a first step. You check with git status. You remove all code that relates to that log file in the index.js git diff now tells you what exactly you had removed and you check visually if the change looks alright: diff --git a/src/App.js b/src/App.js index 3784575..e914079 100644 --- a/src/App.js +++ b/src/App.js @@ -1,11 +1,9 @@ -import logo from './logo.svg'; import './App.css'; function App() { return ( &lt;div className="App"&gt; &lt;header className="App-header"&gt; - &lt;img src={logo} className="App-logo" alt="logo" /&gt; &lt;p&gt; Edit &lt;code&gt;src/App.js&lt;/code&gt; and save to reload. &lt;/p&gt; @@ -22,4 +20,4 @@ function App() { ); } You see that the import logo... line will be removed and so will the line with the &lt;img&gt; tag. You have another look on the real App in the webbrowser and decide that it’s fine. You stage all those changes and commit with: git commit -a -m "Remove default logo and all code referencing it" You convince yourself again that your deletions are recorded nicely, so you can look it up if you ever need it later. You issue git show and see that now you have everyhing together in one commit: The svg-logo-file deletion as well as the deletions of the relevant code lines (you saw a moment ago when checking with git diff prior to committing!) As a final step you check git log and it looks like this: commit 61eacfab5213daa3685329976ed5a259a0fc15f4 (HEAD -&gt; main) Author: J0J0 Todos &lt;jojo@peek-a-boo.at&gt; Date: Thu Jan 18 14:45:08 2024 +0100 Remove default logo and all code referencing it commit ff28dc2bb2b0f40d625e790fbdaf7895041232ec Author: J0J0 Todos &lt;jojo@peek-a-boo.at&gt; Date: Thu Jan 18 14:06:47 2024 +0100 Initialize project using Create React App Whenever you would want to look up how that logo of the default App was implemented, you simply would issue git show 61eacfab52. You do some more cleanup commits but decide that cleaning makes tired. It was an important first step but you need a break. You look forward to starting fresh with an already tidied up project repo after your break :-) Appendix Often beginning developers come from a mostly GUI oriented world of computers. These chapters should give the crashiest of crash courses to command line interfaces. UNIX-like command line tools and shells UNIX-like commands typically follow a pattern with a command accepting options, often with long (--something) and abbreviated (-s) forms. Due to the limited alphabet, shortforms may not be intuitive, but you can find them using --help or -h. A shell, very simply put, is a program that accepts interactive command inputs from a user. Two common ones are named bash and zsh. A shell on a graphical operating system requires a Terminal Emulator Program to be run! So to be exact, a shell is not a Terminal. A Terminal just runs a shell as the very first thing when launched. git-bash, bash and zsh git is a UNIX-like command. I suppose because of its UNIX-like nature, things like git-bash were invented to adapt it for Windows (where command syntax actually follows a different pattern (eg. /s for an option instead of -s). git-bash is a Windows version of the widely-used bash shell known from Linux/BSD/macOS and other *NIX systems. It’s not directly related to the functionality of the git command itself. Nowadays macOS and Linux often use zsh as the default shell, which in fact is a bash-compatible shell. To find out which shell you are using, do echo $SHELL If that points to something like this: /bin/sh, and you still are not sure, do sh --version Configuring your shell To configure your shell, find and edit the .zshrc or .bashrc file in your home directory. If not existing, simply create it! git-bash also uses .bashrc. The cd command without any arguments always sends you “back home”. To find out where your homedirectory is located exactly, use echo $HOME) Append a line to the config file of your shell, to modify the EDITOR environment variable, which sets the default editor for CLI tools like git. For example on Windows to use notepad: export EDITOR="notepad" Restart the shell for changes to take effect (use the exit command). Verify the new setting with echo $EDITOR. It helps to choose an editor that supports syntax highlighting, since Git can display source code within the editor while writing commit-messages. So on Windows you could use notepad++ if you have it installed, or nano, which ships with git-bash, on macOS also try nano. If for some reason setting EDITOR does not work, it could be that Git’s own config overrides it. Check with git config --global --get core.editor Set with git config --global core.editor notepad Configuring git-bash during its setup The git-bash installer asks a ton of questions, those are worth considering: Select Components - Activate “Add a Git Bash Profile to Windows Terminal” Changing the default editor used by Git - Best you leave this at default (vim), because only then you keep the possiblity to control it using the EDITOR shell environment variable. If you’ve had changed it. Configuring the terminal emulator to use with Git Bash - Don’t set to “Use Windows default console window”, keep the default “Use minTTY”! Hint: To change settings after you’ve completed setup already, re-run the git-bash installation fiile. Recommendations on terminal programs Windows The git-bash installation, comes with it’s own terminal emulater named minTTY. Microsofts “own” (but developed open-source) Windows Terminal is a good alternative to minTTY. Hint: To use git-bash as the default shell when opening a new Windows Terminal window, go to its Settings dialog -&gt; Startup -&gt; Default Profile, and select “Git Bash” Hint: Copy marked text in Windows Terminal to the clipboard by using the Return key. Paste text into it with a “Right Click”. macOS On macOS I find the default Terminal app lacking. My recommendation is the Open Source alternative iTerm. It remembers the state of open terminals when your computer reboots (or even crashes), it supports “split panes” and offers loads of other handy features! Linux For Linux, I personally was using Terminator for ages, but nowadays like Konsole. Both supporting “split panes”. Numerous excellent alternatives exist on any Linux distro. VIM editor life jacket vim stands out as a super-powerful text editors that became famous with UNIX admins and programmers because of it’s wide spread availability on commercial *NIX systems as well as Linux and macOS. For those new to vim, its unconventional interface can be intimidating. Here are some life saving concepts you need to know to at least write commit messages with it. If you don’t want to go down that rabbit hole, just reconfigure your shell to use your favorite editor as shown in the previous chapter. vim initiates in the normal mode, requiring commands for actions. Copy lines by moving over them and typing yy. Paste elsewhere with p. (just an example, so you get the idea!) To input characters, switch to insert mode using the i command. While in insert mode, edit as usual. Exit insert mode by pressing Esc (back to normal mode). There’s also an ex mode, accessed with :. Save the file with :w. Quit the file with :q. Save and quit simultaneously with :wq. Many might exclaim, “That is crazy!” Indeed, it might be, but the strength of vim lies in its design for complete mouse-less control. Mastering numerous shortcuts enables swift and efficient editing. Anyway, choose your poison and HTH! Version managers and virtual environments A slightly off-topic chapter around the “dependency hell” new developers will face often. JavaScript programmers want to use NVM, Python programmers have several options, I recommend pyenv. NVM Allows changing the Node version during a shell session with simple commands. Read the installation chapter in the official GitHub repo. nvm usually is installed directly into the the user’s home directory into a hidden directory named .nvm/. A main concept of how it works is it’s simply writing a few lines to the user’s shell configuration (.bashrc, .zshrc). Details if interested in this section of its docs. For developing on Windows there’s another project existing. It’s unrelated to the original nvm project and follows an entirely different approach. Get nvm-windows here Hint: There is a caveat with nvm-windows when being used with git-bash: Due to its differnt nature (not configured via shell configuration files) it does not work when git-bash is run via minTTY (The original “Git Bash” entry in Start Menu!). You have to run git-bash via a Windows Terminal profile as described previously. pyenv pyenv is my recommendation for creating self-contained virtual Python development environments without touching the “built-in” version of the OS. Learn what it does and follow its excellent installation documentation.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.jojotodos.net/images/2024-1-16-git-essentials/Git-Logo-Black.png" /><media:content medium="image" url="https://blog.jojotodos.net/images/2024-1-16-git-essentials/Git-Logo-Black.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Multiple Beets libraries on one machine?</title><link href="https://blog.jojotodos.net/multiple-beets-libs/" rel="alternate" type="text/html" title="Multiple Beets libraries on one machine?" /><published>2022-05-01T00:00:00+00:00</published><updated>2022-05-01T00:00:00+00:00</updated><id>https://blog.jojotodos.net/multiple-beets-libs</id><content type="html" xml:base="https://blog.jojotodos.net/multiple-beets-libs/"><![CDATA[<p>This article is about <a href="https://beets.io">Beets  - the best music library manager out there</a>.</p>

<figure class="sidebyside" style="width: 23%; float: left; margin: 4.5px 10px 0 0; ">
  <img src="/images/2022-5-1-multiple-beets-libs/01.jpg" alt="the Beets beetroot logo" style="border: 5px solid #303030;;" /> 
  <figcaption></figcaption>
</figure>

<p>If you are a music collector who uses command-line tools but haven’t discovered it yet, <a href="https://beets.io">watch its demo video</a> and read the <a href="https://beets.readthedocs.io/en/latest/guides/main.html">Getting Started Guide</a>.</p>

<p>Soon after I started contributing to the Beets project, I wanted to manage multiple Beets libraries installed within a single user account on my macOS and Linux machines. The initial goal was to find a way to quickly switch between testing new code or config settings and working in my main library. Later on I realized the setup’s potential to also make life more comfortable when splitting different content types to separate libraries.</p>

<p> </p>

<p style="text-align:center; font-style:italic; font-weight:bold;">This is not a beginners guide. It describes an opinionated setup for Beets developers and advanced users.</p>

<h2 id="why-more-than-one">Why more than one?</h2>

<p>Currently I run 3 Beets installations:</p>

<ul>
  <li><strong>prod</strong> -&gt; my main Beets library</li>
  <li><strong>dev</strong> -&gt; a development setup I use to play around with new features, test unmerged pull requests, get crazy with the config</li>
  <li><strong>book</strong> -&gt; a separate library I use for audio books about language training, music education practice tracks and actual audio books. The reason I keep this separate is to prevent mixing up music search results (including smartplaylists) with any non-music content.</li>
</ul>

<h2 id="prerequisites">Prerequisites</h2>

<p>This tutorial assumes the following tools installed and set up according to their original documentation:</p>

<ul>
  <li><a href="https://www.zsh.org">Zsh</a></li>
  <li><a href="https://github.com/ohmyzsh/ohmyzsh/">Oh My Zsh</a></li>
  <li><a href="https://github.com/pyenv/pyenv">pyenv</a></li>
  <li>and of course <a href="https://beets.readthedocs.io">Beets</a></li>
</ul>

<p>Beets is assumed to be installed from Git and Python running within a <code class="language-plaintext highlighter-rouge">pyenv</code> controlled virtual environment,</p>

<p>and these <em>Zsh</em> related things should be set up:</p>

<ul>
  <li><em>Oh My Zsh</em> plugins <code class="language-plaintext highlighter-rouge">git</code> and <code class="language-plaintext highlighter-rouge">virtualenv</code> active with their default settings</li>
  <li><a href="https://github.com/ohmyzsh/ohmyzsh/tree/master/plugins/pyenv">Oh My Zsh pyenv plugin</a> configured,</li>
  <li><a href="https://github.com/ohmyzsh/ohmyzsh/?tab=readme-ov-file#themes">Zsh Agnoster theme</a> in use</li>
</ul>

<h2 id="where-to-put-configuration-files">Where to put configuration files?</h2>

<p>The <a href="https://beets.readthedocs.io/en/latest/reference/config.html#default-location">default location for the Beets config.yaml file</a> is <code class="language-plaintext highlighter-rouge">~/.config/beets</code>. We are following this idea and use subdirectories of <code class="language-plaintext highlighter-rouge">~/.config/</code> for all of our three libraries:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">~/.config/beets/config.yaml</code>  for <strong>prod</strong>,</li>
  <li><code class="language-plaintext highlighter-rouge">~/.config/devbeets/config.yaml</code>  for <strong>dev</strong>,</li>
  <li>and <code class="language-plaintext highlighter-rouge">~/.config/bookbeets/config.yaml</code>  for the <strong>book</strong> library.</li>
</ul>

<h2 id="custom-zsh-prompt">Custom Zsh prompt</h2>

<p><strong><em>All of the following setup happens within the Zsh configuration file, usually <code class="language-plaintext highlighter-rouge">~/.zshrc</code></em></strong></p>

<h3 id="beetsdir">$BEETSDIR</h3>

<p>As an alternative to specifiying a Beets config file via the <code class="language-plaintext highlighter-rouge">-c</code> option the <a href="https://beets.readthedocs.io/en/latest/reference/config.html#id131">$BEETSDIR environment variable</a> comes in handy.</p>

<h3 id="pyenv">pyenv</h3>

<p>Your pyenv initialization lines might be slightly different, but generally look similar to this:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">export </span><span class="nv">PYENV_ROOT</span><span class="o">=</span><span class="s2">"</span><span class="nv">$HOME</span><span class="s2">/.pyenv"</span>
<span class="nb">export </span><span class="nv">PATH</span><span class="o">=</span><span class="s2">"</span><span class="nv">$PYENV_ROOT</span><span class="s2">/bin:</span><span class="nv">$PATH</span><span class="s2">"</span>
<span class="nb">eval</span> <span class="s2">"</span><span class="si">$(</span>pyenv init -<span class="si">)</span><span class="s2">"</span>
<span class="nb">eval</span> <span class="s2">"</span><span class="si">$(</span>pyenv virtualenv-init -<span class="si">)</span><span class="s2">"</span>
</code></pre></div></div>

<p>It’s important that the <em>Oh My Zsh</em> pyenv plugin is loaded <em>after</em> pyenv has been initialized, so let’s put this line right below:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>plugins+<span class="o">=(</span>pyenv<span class="o">)</span>
</code></pre></div></div>

<h3 id="agnoster-theme-prompt-functions">Agnoster theme prompt functions</h3>

<p>Ok, so our first goal is to see at all times which Beets library and Python environment is currently active:</p>

<p>To stick together the parts (called “segments”) of the Zsh prompt, the Agnoster theme uses the function <code class="language-plaintext highlighter-rouge">build_prompt</code> which is defined in <code class="language-plaintext highlighter-rouge">~/.oh-my-zsh/themes/agnoster.zsh-theme</code>. The original version looks <a href="https://github.com/ohmyzsh/ohmyzsh/blob/ab3d42a34cd0600b723de0accc248632f2dcf4e3/themes/agnoster.zsh-theme#L257-L269">like this</a>. We simply redefine the function near the end of our <code class="language-plaintext highlighter-rouge">~/.zshrc</code> while adding a new line to it:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>build_prompt <span class="o">()</span> <span class="o">{</span>
        <span class="nv">RETVAL</span><span class="o">=</span><span class="nv">$?</span>
        prompt_status
        prompt_beets  <span class="c"># This is what we add</span>
        prompt_virtualenv
        prompt_context
        prompt_dir
        prompt_git
        prompt_bzr
        prompt_hg
        prompt_end
<span class="o">}</span>
</code></pre></div></div>

<p>We also define a new function named <code class="language-plaintext highlighter-rouge">prompt_beets</code>:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>prompt_beets <span class="o">()</span> <span class="o">{</span>
        <span class="nb">local </span><span class="nv">beetsdir</span><span class="o">=</span><span class="s2">"</span><span class="nv">$BEETSDIR</span><span class="s2">"</span>
        <span class="k">if</span> <span class="o">[[</span> <span class="s2">"</span><span class="nv">$beetsdir</span><span class="s2">"</span> <span class="o">=</span>~ <span class="s2">".*/beets$"</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then
                </span>prompt_segment 0 1 <span class="s2">"prod"</span>
        <span class="k">elif</span> <span class="o">[[</span> <span class="s2">"</span><span class="nv">$beetsdir</span><span class="s2">"</span> <span class="o">=</span>~ <span class="s2">".*/devbeets$"</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then
                </span>prompt_segment 0 2 <span class="s2">"dev"</span>
        <span class="k">elif</span> <span class="o">[[</span> <span class="s2">"</span><span class="nv">$beetsdir</span><span class="s2">"</span> <span class="o">=</span>~ <span class="s2">".*/bookbeets$"</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then
                </span>prompt_segment 0 2 <span class="s2">"books"</span>
        <span class="k">elif</span> <span class="o">[[</span> <span class="nt">-z</span> <span class="nv">$beetsdir</span> <span class="o">]]</span>  <span class="o">&amp;&amp;</span> <span class="se">\</span>
             <span class="o">[[</span> <span class="nt">-z</span> <span class="s2">"</span><span class="nv">$PYENV_VERSION</span><span class="s2">"</span> <span class="o">]]</span> <span class="o">&amp;&amp;</span> <span class="se">\</span>
             <span class="o">[[</span> <span class="nt">-z</span> <span class="s2">"</span><span class="nv">$VIRTUAL_ENV</span><span class="s2">"</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then
                </span>prompt_segment 1 0 <span class="s2">"sys-py"</span>
        <span class="k">fi</span>
<span class="o">}</span>
</code></pre></div></div>
<p>What this does is look up what config file is currently active according to <code class="language-plaintext highlighter-rouge">$BEETSDIR</code> and return a snippet defining how the prompt segment should look like. Play around with the two digits after <code class="language-plaintext highlighter-rouge">prompt_segment</code> to set fore- and background colors of the string displayed!</p>

<p>So for example if <code class="language-plaintext highlighter-rouge">$BEETSDIR</code> is set to <code class="language-plaintext highlighter-rouge">~/.config/devbeets</code> we would get a prompt like this:</p>

<figure class="sidebyside" style="width: 75%; float: ; margin: ; ">
  <img src="/images/2022-5-1-multiple-beets-libs/02.jpg" alt="" style=";" /> 
  <figcaption></figcaption>
</figure>

<p>As a nice additional feature, which is not only Beets-related, I personally like to have a fallback that tells me that I’m not in any virtual environment and the <em>system’s Python installation</em> is active. <code class="language-plaintext highlighter-rouge">1 0</code> here means an alerting red background and white as the foreground color. We’ll find out how that looks like further below. No spoilers now :-P</p>

<h3 id="customizing-how-the-virtualenv-plugin-alters-the-prompt">Customizing how the virtualenv plugin alters the prompt</h3>

<p>Additionally we are changing the original format of the segment generated by the <em>Oh My Zsh</em> <code class="language-plaintext highlighter-rouge">virtualenv</code> plugin. As we saw in the screenshot above it uses parentheses around the environment name and the same background color as the prompt. We want to remove parentheses and change colors:</p>

<figure class="sidebyside" style="width: 75%; float: ; margin: ; ">
  <img src="/images/2022-5-1-multiple-beets-libs/04.jpg" alt="" style=";" /> 
  <figcaption></figcaption>
</figure>

<p>We achieve this by overwriting the original <code class="language-plaintext highlighter-rouge">prompt_virtualenv()</code> function which is defined <a href="https://github.com/ohmyzsh/ohmyzsh/blob/ab3d42a34cd0600b723de0accc248632f2dcf4e3/themes/agnoster.zsh-theme#L223-L228">here in the original code of the Agnoster theme</a>. We can use literal color names too:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>prompt_virtualenv<span class="o">()</span> <span class="o">{</span>
  <span class="k">if</span> <span class="o">[[</span> <span class="nt">-n</span> <span class="s2">"</span><span class="nv">$VIRTUAL_ENV</span><span class="s2">"</span> <span class="o">&amp;&amp;</span> <span class="nt">-n</span> <span class="s2">"</span><span class="nv">$VIRTUAL_ENV_DISABLE_PROMPT</span><span class="s2">"</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then
      </span>prompt_segment white black <span class="s2">"</span><span class="k">${</span><span class="nv">VIRTUAL_ENV</span>:t:gs/%/%%<span class="k">}</span><span class="s2">"</span>
  <span class="k">fi</span>
<span class="o">}</span>
</code></pre></div></div>

<h2 id="shell-aliases-for-switching-the-active-library">Shell aliases for switching the active library</h2>

<p>We add an alias for each library in our <code class="language-plaintext highlighter-rouge">.zshrc</code>. If desired at this point we could also activate a specific virtual Python environment simultaneously using the <code class="language-plaintext highlighter-rouge">pyenv activate</code> command. Another convenience feature I like is to directly jump to Beets source code.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">bdev</span><span class="o">=</span><span class="s2">"export BEETSDIR=~/.config/devbeets; pyenv activate beets311; cd ~/git/beet"</span>
<span class="nv">bprod</span><span class="o">=</span><span class="s2">"export BEETSDIR=~/.config/beets; pyenv activate beets310; cd ~/git/beets"</span>
<span class="nv">bbook</span><span class="o">=</span><span class="s2">"export BEETSDIR=~/.config/bookbeets; pyenv activate beets311; cd ~/git/beet"</span>
</code></pre></div></div>
<p>We saw the <code class="language-plaintext highlighter-rouge">dev</code> environment prompt above already - this is what we get if we now switch with <code class="language-plaintext highlighter-rouge">bprod</code> or <code class="language-plaintext highlighter-rouge">bbook</code>:</p>

<figure class="sidebyside" style="width: 75%; float: ; margin: ; ">
  <img src="/images/2022-5-1-multiple-beets-libs/03.jpg" alt="" style=";" /> 
  <figcaption></figcaption>
</figure>

<figure class="sidebyside" style="width: 75%; float: ; margin: ; ">
  <img src="/images/2022-5-1-multiple-beets-libs/05.jpg" alt="" style=";" /> 
  <figcaption></figcaption>
</figure>

<p>To quit working/using Beets I also define a quit alias - actually I use it to quit <em>any</em> <code class="language-plaintext highlighter-rouge">pyenv</code> controlled environment and the <code class="language-plaintext highlighter-rouge">b</code>-prefix is not perfectly appropriate - but who cares?</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">bquit</span><span class="o">=</span><span class="s2">"unset BEETSDIR; pyenv deactivate"</span>
</code></pre></div></div>

<p>So since <code class="language-plaintext highlighter-rouge">bquit</code> deactivates any Python virtual environment we’ll fall back to alerting <code class="language-plaintext highlighter-rouge">sys-py</code> prompt we talked above:</p>

<figure class="sidebyside" style="width: 75%; float: ; margin: ; ">
  <img src="/images/2022-5-1-multiple-beets-libs/06.jpg" alt="" style=";" /> 
  <figcaption></figcaption>
</figure>

<p>I hope this is of use to fellow Beeters. Please tell me what you think! I’m very interested in your own ideas of handling multiple Beets environments and how this setup could be advanced further!</p>]]></content><author><name></name></author><summary type="html"><![CDATA[This article is about Beets - the best music library manager out there.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.jojotodos.net/images/2022-5-1-multiple-beets-libs/01-th.jpg" /><media:content medium="image" url="https://blog.jojotodos.net/images/2022-5-1-multiple-beets-libs/01-th.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">DiscoDOS - The geekiest DJ tool on the planet</title><link href="https://blog.jojotodos.net/discodos-v1-0/" rel="alternate" type="text/html" title="DiscoDOS - The geekiest DJ tool on the planet" /><published>2021-03-21T00:00:00+00:00</published><updated>2021-03-21T00:00:00+00:00</updated><id>https://blog.jojotodos.net/discodos-v1-0</id><content type="html" xml:base="https://blog.jojotodos.net/discodos-v1-0/"><![CDATA[<p>Last weekend I released the final 1.0 version of DiscoDOS. Since it got its
own website, there shouldn’t be much to say in this blog post. So head over
to <a href="https://discodos.jojotodos.net">discodos.jojotodos.net</a> and read all
about it!</p>

<figure class="sidebyside" style="width: 35%; float: left; margin: 4.5px 10px 0 0; ">
  <img src="https://discodos.jojotodos.net/images/discodos_7-v7_big_fat_D_altrosa_960x960.png" alt="very large DiscoDOS icon" style=";" /> 
  <figcaption></figcaption>
</figure>

<p>But wait, why not leave a little big history here?</p>

<p>Back in autumn 2018 I decided that it’s about time for my DJ set notes to
move from my Moleskin notebook to a proper digital version. Before that, I
went for some clumsy excourses using spreadsheet software. I wrote down my
set lists and also tried to put in my pool of records but as always
spreadsheets are not a database, data is doubled, constantly has to be
copied around, all is basically just errorprone and a nightmare to keep
up-to-date. Hence Moleskin and my favorite pencil stayed my best option for a
very long time.</p>

<p>The idea of using what is already there - my personal record collection on
discogs.com - and not reinventing the wheel too much probably was in my head
a long time ago but since my programming skills only became decent enough
roughly during the last 5 years, probably it took that long until I decided
that I’m good enough to do it.</p>

<p>First hackish approaches were finished in a couple of weeks - I
could import my records from Discogs into a local SQLite database, search my
collection, create mixes and it was usable good enough for
me personally.</p>

<p>By the start of 2019 I called it a version 0.0.1 but at the same time decided
that my code was crap and since I was just about to understand a lot more
programming concepts I started refactoring a lot of the original code,
rewrote things entirely and threw away old code.</p>

<p>Somewhere in the middle of 2019 my friend F. joined the project. He was eager
to learn GUI programming in Python and started to build a Tkinter version of
DiscoDOS. Also this gave me a lot of thought and motivation on improving the
backend code, so again a lot of stuff was refactored, improved and thrown
away. Also around this time I decided that since Python is cross platform but
not every DJ knows how to install Python software out of a github repo, there
should be proper support for the major Desktop platforms. My journey on
learning on how to package for Windows and macOS began.</p>

<p>By the start of 2020 I actually thought “We are almost 1.0 now, just a couple
of things”, but things turned out differently and a couple of months passed
until the first release candidate came out by the end of April. I think it
was exactely the 1st of May actually, which usually is a great day and kind
of starts summer for me ;-)</p>

<p>Since I am a fan of Open Source software, especially Linux, since the late
90’s, my next decision for gathering even more work was obvious: “There needs
to be a software package for Debian GNU/Linux”.</p>

<p>Again this was new territory for me and it took another 1-2 months to get it
straight. Since I learned a lot more about proper Python packaging and Debian
being pretty strict on how a package has to look like (for understandable
reasons), major things had to be changed and also a lot of work went into
macOS and Windows packaging again.</p>

<p>After the next release candidates around June 2020 I took a break from the
project since there where other things to do (too many projects as usual) and
actually I was happy that DiscoDOS made it that far and was pretty darn
stable already.</p>

<p>And now we are here: Between January 2021 and last week I fixed and
refactored a couple of things I was aware of since a long time already but
never found the time to do. I teached myself on how to use the Sphinx
framework to build beautiful documentation, built a website, packaging for
macOS was improved again and most importantly: Both Windows and macOS
packaging was automated pretty good using oldschool bash magic but also using
the wonderful CI/CD pipeline possibilites of github actions, which will keep
me from fiddling around with boring, errorprone packaging stuff ever
again… famous last words… ;-)</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Last weekend I released the final 1.0 version of DiscoDOS. Since it got its own website, there shouldn’t be much to say in this blog post. So head over to discodos.jojotodos.net and read all about it!]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://discodos.jojotodos.net/images/discodos_7-v7_big_fat_D_altrosa_960x960.png" /><media:content medium="image" url="https://discodos.jojotodos.net/images/discodos_7-v7_big_fat_D_altrosa_960x960.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Akai MPC tool updated to v1.2</title><link href="https://blog.jojotodos.net/mpc1k-seq-v1-2/" rel="alternate" type="text/html" title="Akai MPC tool updated to v1.2" /><published>2020-01-18T00:00:00+00:00</published><updated>2020-01-18T00:00:00+00:00</updated><id>https://blog.jojotodos.net/mpc1k-seq-v1-2</id><content type="html" xml:base="https://blog.jojotodos.net/mpc1k-seq-v1-2/"><![CDATA[<p>I just released a new version of my “AKAI MPC 1000 sequence file command line utility”.</p>

<figure class="sidebyside" style="width: 49%; float: left; margin: 4.5px 10px 0 0; ">
  <img src="/images/2018-4-15-mpc1k-seq/IMG_0461.jpg" alt="some sequences on the MPC" style="border: 5px solid #303030; //rgb(255, 129, 173);;" /> 
  <figcaption></figcaption>
</figure>

<p>Probably the biggest news is that you now don’t need any form of Python installed on your computer, because I provide executable files for MacOS and Windows that contain all the Python stuff the tool needs. Full release notes and download here: <a href="https://github.com/JOJ0/mpc1k-seq/releases/tag/v1.2">mpc1k-seq version 1.2</a></p>

<p>Read what this tool is actually about in the <a href="/mpc1k-seq/">updated original blog post</a>.</p>

<p>And as always: your valuable feedback is appreciated!</p>]]></content><author><name></name></author><summary type="html"><![CDATA[I just released a new version of my “AKAI MPC 1000 sequence file command line utility”.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.jojotodos.net/images/2018-4-15-mpc1k-seq/IMG_0461-th.jpg" /><media:content medium="image" url="https://blog.jojotodos.net/images/2018-4-15-mpc1k-seq/IMG_0461-th.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Schmiede19 MIDILAB</title><link href="https://blog.jojotodos.net/midilab/" rel="alternate" type="text/html" title="Schmiede19 MIDILAB" /><published>2019-09-13T00:00:00+00:00</published><updated>2019-09-13T00:00:00+00:00</updated><id>https://blog.jojotodos.net/midilab</id><content type="html" xml:base="https://blog.jojotodos.net/midilab/"><![CDATA[<p>This post developed during the DIY MIDI controller workshop at Schmiede 2019 in Hallein (Austria). It was used as a presentation and documentation tool.</p>

<p><a name="midi"></a></p>
<h2 id="what-can-we-do-with-midi">What can we do with MIDI?</h2>

<ul>
  <li>Play notes</li>
  <li>Change parameters</li>
  <li>Change programs/presets</li>
  <li>…</li>
</ul>

<h2 id="what-is-midi">What is MIDI?</h2>

<ul>
  <li>a serial communication protocol</li>
  <li>bitrate of 31250 bps (bits per second), also called “baud rate”</li>
  <li>each message consists of 2 or 3 bytes</li>
</ul>

<h3 id="midi-messages">MIDI messages</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>| Value (dec) | Value (Hex) | Command          | Data bytes                |
| ------------| ----------- | ---------------  | ------------------------- |
| 128-143     | 80-8F       | Note off         | 2 (note, velocity)        |
| 144-159     | 90-9F       | Note on          | 2 (note, velocity)        |
| 160-175     | A0-AF       | Key Pressure     | 2 (note, key pressure)    |
| 176-191     | B0-BF       | Control Change   | 2 (controller no., value) |
| 192-207     | C0-CF       | Program Change   | 1 (program no.)           |
| 208-223     | D0-DF       | Channel Pressure | 1 (pressure)              |
| 224-239     | E0-EF       | Pitch Bend       |                           |
| ------------| ----------- | ---------------- | --------------------------|
</code></pre></div></div>

<p>16 MIDI channels</p>

<p>Note byte 1 (channel):</p>
<ul>
  <li>Channel 1: 144</li>
  <li>Channel 2: 145</li>
  <li>Channel 16: 159</li>
</ul>

<p>Note byte 2 (note number):</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>C0  = 0
C1  = 24
C#1 = 25
C4  = 60
A4  = 60
C5  = 72
</code></pre></div></div>

<p><a href="https://glassarmonica.com/science/frequency_midi.php">MIDI note numbers list</a></p>

<p><a href="https://newt.phys.unsw.edu.au/jw/notes.html">another MIDI note numbers list</a></p>

<p>CC message:</p>
<ul>
  <li>Channel 1: 176</li>
  <li>Channel 2: 177</li>
  <li>Channel 16: 191</li>
</ul>

<h4 id="examples">Examples</h4>

<p>Send a NoteOn message for the note of D#3 on channel 1 with a velocity of 90:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>144 | 36 | 90
</code></pre></div></div>

<p>Send a Control Change message for Controller number 81 on channel 2 with a value of 65</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>177 | 81 | 65
</code></pre></div></div>

<p><br />
Can we choose any CC number for our controller?</p>

<p><a href="http://nickfever.com/music/midi-cc-list">midi cc list</a></p>

<p><a name="hardware"></a></p>
<h2 id="getting-to-know-the-hardware">Getting to know the hardware</h2>

<p><a href="https://www.arduino.cc/en/products.compare">official Arduino specs comparision table</a></p>

<h3 id="nano-pinout">Nano pinout</h3>

<div class="clearfix">
  


<figure class="sidebyside" style="width: 100%; float: left; margin: ; ">
  <a href="/images/2019-9-13-midilab/nano_pins_color.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2019-9-13-midilab/nano_pins_color-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;"></figcaption>
</figure>



</div>
<p><br /></p>

<h3 id="pro-micro-pinout">Pro Micro pinout</h3>

<div class="clearfix">
  


<figure class="sidebyside" style="width: 100%; float: left; margin: ; ">
  <a href="/images/2019-9-13-midilab/pro_micro_pins_color.png">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2019-9-13-midilab/pro_micro_pins_color-th.png" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;"></figcaption>
</figure>



</div>

<h3 id="nano-specifics">Nano specifics</h3>

<p>The Nano is very similar to the well-known Arduino Uno, it only is smaller and has more connection possibilities.</p>

<h4 id="chinese-nano-clones-ch340">Chinese Nano clones (CH340)</h4>

<p>The Arduino Nano clones we use, have a CH340 chip that does the USB to serial conversion. To program it we need a USB-driver specific to our computers operating system.</p>

<p><a href="https://blog.sengotta.net/signed-mac-os-driver-for-winchiphead-ch340-serial-bridge/">For Mac OS X High Sierra and above we need this driver</a></p>

<p><a href="https://sparks.gogo.co.nz/ch340.html">For Windows 10 we need this one</a></p>

<h5 id="programming-settings">Programming settings</h5>

<p>Golden USB socket version:</p>
<ul>
  <li>Board: <em>Arduino Nano</em></li>
  <li>Processor: <em>ATmega328b</em></li>
</ul>

<p>Silver USB socket version:</p>
<ul>
  <li>Board: <em>Arduino Nano</em></li>
  <li>Processor: <em>ATmega328b (old bootloader)</em></li>
</ul>

<p>Both types:</p>
<ul>
  <li>Select the correct serial port
    <ul>
      <li>Mac OS X: something called /dev/cu.something (eg. /dev/cu.wchusbserial1410)</li>
      <li>Windows: COMx (eg COM4, COM10, …)
        <ul>
          <li>use the <em>Devicemanager</em> to find out which COM port appears when you connect the Arduino to the USB port</li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

<p>If our programming settings or the CH340 driver are wrong this is one of the possible errors:</p>

<p><code class="language-plaintext highlighter-rouge">avrdude: stk500_getsync(): not in sync: resp=0x00</code></p>

<h3 id="pro-micro-specifics">Pro Micro specifics</h3>

<p><a href="https://learn.sparkfun.com/tutorials/pro-micro--fio-v3-hookup-guide/hardware-overview-pro-micro">Sparkfun Pro Micro hookup guide</a></p>

<p><a href="https://www.youtube.com/watch?v=y0v2clCVw9k">nice Pro Micro connections video-tutorial, also about multiplexing input</a></p>

<h4 id="chinese-pro-micro-clones">Chinese Pro Micro clones</h4>

<p>Specifically this chip: ATmega32U4 5V 16MHz</p>

<h5 id="programming-settings-1">Programming settings</h5>
<ul>
  <li>Board: <em>Arduino Leonardo</em></li>
  <li>Select the correct serial port
    <ul>
      <li>Mac OS X: something called /dev/cu.something</li>
      <li>Windows: COMx (eg COM4, COM10, …)
        <ul>
          <li>use the <em>Devicemanager</em> to find out which COM port appears when you connect the Arduino to the USB port</li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

<h2 id="wiring-power-connections-and-a-button">Wiring power connections and a button</h2>

<p>To power the plus- and minus-rails of our breadboard we connect the <em>5V</em> and <em>GND</em> pins to it. On the <em>Pro Micro</em> the <em>5V</em> pin is called <em>VCC</em>.</p>

<div class="clearfix">
  


<figure class="sidebyside" style="width: 100%; float: left; margin: ; ">
  <a href="/images/2019-9-13-midilab/vcc_ground_switch.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2019-9-13-midilab/vcc_ground_switch-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">The position of the switch and its wiring on the breadboard is <strong>wrong in this pic</strong> and can damage the Arduino! Refer to the pics in chapter <a href="#wiring_midi">Wiring the MIDI socket</a> for the correct position and wiring of the switch.</figcaption>
</figure>






</div>

<h3 id="so-why-is-position-and-wiring-of-the-switch-wrong">So why is position and wiring of the switch wrong?</h3>

<p>The short answer is: Because we assumed that these switches work similar to a lot of other switch types.</p>

<p>The square-button-switches we use are so called DPDT switches (Dual Pole Double Throw). This basically means that we can use them to <em>switch on/off</em> or <em>toggle</em> two things with one buttonpress. Or put differently: Two switches in one.</p>

<div class="clearfix">
  


<figure class="sidebyside" style="width: 59%; float: left; margin: ; ">
  <a href="/images/2019-9-13-midilab/dpdt_toggle_switch_diagram.png">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2019-9-13-midilab/dpdt_toggle_switch_diagram-th.png" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">This is how a regular DPDT switch works. Pins 1, 3, 5 represent one toggle switch and pins 2, 4, 6 the other one. If we would plug in one of <em>those</em> into the breadboard as shown on the photograph above we would be perfectly fine: Even though we connected some pins together via the vertical rows of the breadboard (pin-pairs 1+2, 3+4 and 5+6 would connect), everything would be working as it should: Our goal is to connect <strong>one</strong> Arduino pin (D2) to either 5V or GND (high or low). We actually don&#39;t care that we can&#39;t use the second switch in our DPDT anymore.</figcaption>
</figure>




  


<figure class="sidebyside" style="width: 39%; float: right; margin: ; ">
  <a href="/images/2019-9-13-midilab/dpdt_push_switch_diagram.png">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2019-9-13-midilab/dpdt_push_switch_diagram-th.png" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">The switches <em>we</em> use are also DPDT switches that certainly can also be used to toggle two things at a time, only that their two (vertical) pin rows don&#39;t operate <em>in parallel</em> - their pinout is completely different.
</figcaption>
</figure>



</div>
<p><br /></p>

<p>Let's assume the same pin numbering as on the regular DPDT diagram on the left, for our oddly wired switches on the right: In off-state 1+5 and 2+6 connect. In on-state it's 1+3 and 4+6.</p>

<p>So what actually happens when we plug in the power to the breadboard (connect the Arduino to a USB port) and keep the button unpressed, is: We connect + and - poles together (via pins 1 and 5) and thus short-circuit the Arduino which it can withstand for a short time only.</p>

<p>To correctly wire these types of switches we need to:</p>
<ul>
  <li>plug them into the middle of the breadboard so the two <em>3-pin-rows</em> aka the <em>2 switches</em> are isolated from each other.</li>
  <li>use pin 5 (bottom-right / blue wire on pic below) to connect to the Arduinos input (D2).</li>
  <li>in unpressed state pin 1 (bottom-left / green wire) and pin 5 are connected and thus D2 is connected to GND</li>
  <li>in pressed state pin 1 (middle / purple wire) and pin 3 are connected and thus D2 is connected to 5V.</li>
</ul>

<p><a name="wiring_midi"></a></p>
<h2 id="wiring-the-midi-socket">Wiring the MIDI socket</h2>

<div class="clearfix">
  


<figure class="sidebyside" style="width: 49%; float: left; margin: ; ">
  <a href="/images/2019-9-13-midilab/schematic_midi_output.png">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2019-9-13-midilab/schematic_midi_output-th.png" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">This schematic shows the socket from the backside (the soldering side)</figcaption>
</figure>



  


<figure class="sidebyside" style="width: 49%; float: right; margin: ; ">
  <a href="/images/2019-9-13-midilab/midi_din_case.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2019-9-13-midilab/midi_din_case-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">The socket is held as on the schematic. We are looking at the soldering side. The socket&#39;s TX pin is the orange wire on the top-left.</figcaption>
</figure>



</div>
<p><br /></p>

<div class="clearfix">
  


<figure class="sidebyside" style="width: 49%; float: left; margin: ; ">
  <a href="/images/2019-9-13-midilab/midi_din_breadboard.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2019-9-13-midilab/midi_din_breadboard-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">Be aware of that the circuit-/breadboard socket is flipped upside-down compared to the wiring schematic above! The TX pin is the violet wire on the (bottom-)right.</figcaption>
</figure>



  


<figure class="sidebyside" style="width: 49%; float: right; margin: ; ">
  <a href="/images/2019-9-13-midilab/midi_din_breadboard_pins.png">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2019-9-13-midilab/midi_din_breadboard_pins-th.png" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">A circuitboard/breadboard socket seen from the front. The TX pin (5) would be bottom-left now</figcaption>
</figure>



</div>
<p><br /></p>

<p>For more detailed schematics and information on MIDI Output and MIDI input wiring refer to the official <a href="https://www.midi.org/specifications-old/item/midi-din-electrical-specification">MIDI specification of the MIDI manufacturers association</a></p>

<p><a name="wiring_midi"></a></p>
<h2 id="wiring-a-potentiometer">Wiring a potentiometer</h2>

<div class="clearfix">
  


<figure class="sidebyside" style="width: 100%; float: right; margin: ; ">
  <a href="/images/2019-9-13-midilab/pot.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2019-9-13-midilab/pot-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">The output of a pot usually is the middle pin (but as we learned earlier never trust on this! ;-)). It&#34;s connected to the Arduinos analog input pin A0. The left pin (purple) we connect to ground and the right pin (green) to 5V.</figcaption>
</figure>



</div>

<p><br />
When we twist the knob to the left we decrease the resistance between ground (purple wire) and the pots output (yellow wire) until it is 0 Ohms. When twisted to the right the resistance between the two wires increases until it reaches almost the nominal value of the pot (10kOhms). The actual Ohms are not of interest when using pots with Arduinos. When we read out the current value of an analog input we always receive a number between 0 and 1023</p>

<p>There is a second yellow wire that is supposed to be connected to a second pot but for now we put it on ground so the Arduinos input A1 does not deliver measuring values and disturb us while coding and/or debugging.</p>

<h2 id="coding">Coding</h2>

<p><a href="https://github.com/JOJ0/midilab">The code we produce is available on this github repo</a></p>

<p>Direct links to “git commits”:</p>

<p><a href="https://github.com/JOJ0/midilab/blob/4373c414d803a348d799914d412ad94fbd72badb/midilab.ino">final code day 1 - reading in a button’s state</a></p>

<p><a href="https://github.com/JOJ0/midilab/blob/a14eb79253ec428675e477e2c885c6f3f10fb892/midilab.ino">final code day 2 - sending out midi CC on and off</a></p>

<p><a href="https://github.com/JOJ0/midilab/blob/2341d159cfd79cf7d36ab147d809c944b6615084/midilab.ino">day 3 - four switches for-loop example</a></p>

<p><a href="https://github.com/JOJ0/midilab/blob/601bf655e5893350eff4a27f8f06143a91a295ae/midilab.ino">day 3 - two pots for-loop example</a>
<br /><br /></p>

<h4 id="thanks-a-lot-to-all-the-particpants-you-really-were-lovely-and-it-was-a-pleasure-to-teach-you">Thanks a lot to all the particpants! You really were lovely and it was a pleasure to teach you!</h4>
<p><br /></p>]]></content><author><name></name></author><summary type="html"><![CDATA[This post developed during the DIY MIDI controller workshop at Schmiede 2019 in Hallein (Austria). It was used as a presentation and documentation tool.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.jojotodos.net/images/2019-9-13-midilab/pro_micro_pins_color.png" /><media:content medium="image" url="https://blog.jojotodos.net/images/2019-9-13-midilab/pro_micro_pins_color.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Machinedrum Phones Socket Replace</title><link href="https://blog.jojotodos.net/mach-drm/" rel="alternate" type="text/html" title="Machinedrum Phones Socket Replace" /><published>2019-03-22T00:00:00+00:00</published><updated>2019-03-22T00:00:00+00:00</updated><id>https://blog.jojotodos.net/mach-drm</id><content type="html" xml:base="https://blog.jojotodos.net/mach-drm/"><![CDATA[<p>Back in 2019, P. came to me to help them do some soldering. They had a regular pcb-mount phones socket (6.3 mm, 1/4″) and the legendary Elektron Machinedrum in the luggage.</p>

<p>“No P., we don’t <em>do</em> premium content on this blog! It’s <em>para todos</em>!”</p>

<p>Alright, so this is replacing the Machinedrum’s phones socket explained in pictures, not words!</p>

<div class="photo-gallery-frame clearfix">
  <ul class="photo-gallery-list">
    
    <li>
      <a href="/mach-drm/01/" name="01">
        <img src="/images/2019-3-22-mach-drm/01-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/02/" name="02">
        <img src="/images/2019-3-22-mach-drm/02-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/03/" name="03">
        <img src="/images/2019-3-22-mach-drm/03-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/04/" name="04">
        <img src="/images/2019-3-22-mach-drm/04-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/05/" name="05">
        <img src="/images/2019-3-22-mach-drm/05-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/06/" name="06">
        <img src="/images/2019-3-22-mach-drm/06-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/07/" name="07">
        <img src="/images/2019-3-22-mach-drm/07-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/08/" name="08">
        <img src="/images/2019-3-22-mach-drm/08-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/09/" name="09">
        <img src="/images/2019-3-22-mach-drm/09-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/10/" name="10">
        <img src="/images/2019-3-22-mach-drm/10-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/11/" name="11">
        <img src="/images/2019-3-22-mach-drm/11-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/12/" name="12">
        <img src="/images/2019-3-22-mach-drm/12-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/13/" name="13">
        <img src="/images/2019-3-22-mach-drm/13-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/14/" name="14">
        <img src="/images/2019-3-22-mach-drm/14-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/15/" name="15">
        <img src="/images/2019-3-22-mach-drm/15-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/16/" name="16">
        <img src="/images/2019-3-22-mach-drm/16-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/17/" name="17">
        <img src="/images/2019-3-22-mach-drm/17-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/18/" name="18">
        <img src="/images/2019-3-22-mach-drm/18-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/19/" name="19">
        <img src="/images/2019-3-22-mach-drm/19-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/20/" name="20">
        <img src="/images/2019-3-22-mach-drm/20-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/21/" name="21">
        <img src="/images/2019-3-22-mach-drm/21-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/22/" name="22">
        <img src="/images/2019-3-22-mach-drm/22-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/23/" name="23">
        <img src="/images/2019-3-22-mach-drm/23-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/24/" name="24">
        <img src="/images/2019-3-22-mach-drm/24-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/25/" name="25">
        <img src="/images/2019-3-22-mach-drm/25-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/26/" name="26">
        <img src="/images/2019-3-22-mach-drm/26-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/27/" name="27">
        <img src="/images/2019-3-22-mach-drm/27-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/28/" name="28">
        <img src="/images/2019-3-22-mach-drm/28-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/29/" name="29">
        <img src="/images/2019-3-22-mach-drm/29-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/30/" name="30">
        <img src="/images/2019-3-22-mach-drm/30-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/31/" name="31">
        <img src="/images/2019-3-22-mach-drm/31-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/32/" name="32">
        <img src="/images/2019-3-22-mach-drm/32-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/33/" name="33">
        <img src="/images/2019-3-22-mach-drm/33-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/34/" name="34">
        <img src="/images/2019-3-22-mach-drm/34-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/35/" name="35">
        <img src="/images/2019-3-22-mach-drm/35-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/36/" name="36">
        <img src="/images/2019-3-22-mach-drm/36-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/37/" name="37">
        <img src="/images/2019-3-22-mach-drm/37-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
    <li>
      <a href="/mach-drm/38/" name="38">
        <img src="/images/2019-3-22-mach-drm/38-th.jpg" alt="" style="width: 31%" />
      </a>
    </li>
    
  </ul>
</div>

<h3 id="machinedrumming-again-3">Machinedrumming again &lt;3</h3>

<!-- If a width is specified, most probably the video should be displayed "inline", thus disable margins -->

<div class="outer_ytcontainer" style="width: 100%; margin-top:0 auto; margin-left:0 auto; margin-right:0 auto">

  <div class="ytcontainer">
    <iframe class="yt" allowfullscreen="" src="https://www.youtube.com/embed/CXkVZGCcJv8"></iframe>
  </div>
</div>

<p><br /><br /></p>]]></content><author><name></name></author><summary type="html"><![CDATA[Back in 2019, P. came to me to help them do some soldering. They had a regular pcb-mount phones socket (6.3 mm, 1/4″) and the legendary Elektron Machinedrum in the luggage.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.jojotodos.net/images/2019-3-22-mach-drm/37.jpg" /><media:content medium="image" url="https://blog.jojotodos.net/images/2019-3-22-mach-drm/37.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Building MIDI controllers #1 - The Matrix</title><link href="https://blog.jojotodos.net/midictrl1/" rel="alternate" type="text/html" title="Building MIDI controllers #1 - The Matrix" /><published>2018-11-17T00:00:00+00:00</published><updated>2018-11-17T00:00:00+00:00</updated><id>https://blog.jojotodos.net/midictrl1</id><content type="html" xml:base="https://blog.jojotodos.net/midictrl1/"><![CDATA[<p>MIDI controllers are not the most complicated things on earth to build and program.</p>

<p>If you have your MIDI basics covered and have a little experience with Arduino-type microcontrollers it’s just a matter of capturing an inputdevice (button, knob, …) into your microcontroller and sending some bytes out via a serial port, which MIDI essentially is.</p>

<p>There is a lot about building basic MIDI controllers on the net already so I won’t cover that, but give an overview of what helped me to get going:</p>

<ul>
  <li><a href="https://www.youtube.com/watch?v=0L7WAMFWSgY&amp;index=80&amp;t=0s&amp;list=PLcHqk0rpp8br1wTI-LeNKtxVmEKB1YT8O">This</a> is probably the best explanation of how MIDI circuits really work from an electrical point of view.</li>
  <li><a href="https://www.youtube.com/watch?v=DXhxdsGREsU">This basic MIDI controllers tutorial</a> is from the same guy but unfortunately he doesn’t explain much how it actually works, you won’t learn coding with this one.</li>
  <li><a href="https://www.youtube.com/playlist?list=PL8ANKYeWEXshCLOS9sFfcQNigYXEb1Ps6">Video series </a> in german language for absolute beginners without any Arduino experience. Also he doesn’t use any libraries but explains how to do everything from scratch. Valuable!</li>
  <li><a href="https://www.youtube.com/watch?v=aVf_el4N0tI&amp;t=54s">This video</a> is quite nice, he’s using a Teensy microcontroller which has MIDI over USB by default</li>
</ul>

<p>Speaking of: just to get one slightly dissapointing thing straight from the beginning: Most of the common Arduino types are not capable of natively spitting out MIDI on their USB ports, but I’m going to show a hardware-hackish approach to still make it work. A few Arduinos have native USB capabilities and can make use of the <a href="https://github.com/arduino-libraries/MIDIUSB">MIDIUSB library</a> , but that’s usually the type of Arduino you don’t have at hand at the right moment. The only one’s that have USB-MIDI out of the box are the Teensy’s but they cost a little more, if you don’t want any hassle go get one! <a href="https://www.pjrc.com/teensy/">This is the website of the founder</a>, you’ll find excellent documentation there.</p>

<h2 id="the-input-device">The input device</h2>

<p>This is going to be my chosen input device, a button matrix out of a 1995 landline phone, built by the company Kapsch, model TP80.</p>

<div class="clearfix" style="margin-bottom: 20px;">



<figure class="sidebyside" style="width: 49%; float: left; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-01.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-01-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">I got these phone parts out of a spare parts collection</figcaption>
</figure>






<figure class="sidebyside" style="width: 49%; float: right; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-02.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-02-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">There was another PCB connected to the actual buttons PCB that had to be desoldered first</figcaption>
</figure>



</div>

<p><a name="understanding"></a></p>
<h3 id="understanding">Understanding</h3>

<p>So wtf is a key matrix? <a href="https://www.youtube.com/watch?v=DlW77pAyDx4&amp;t=1s&amp;list=PLcHqk0rpp8br1wTI-LeNKtxVmEKB1YT8O&amp;index=5">This guy</a> explains it quite well, just ignore the voltage ladder for now. <a href="https://www.youtube.com/watch?v=vaqzTHOvpH8&amp;t=1604s&amp;list=PLcHqk0rpp8br1wTI-LeNKtxVmEKB1YT8O&amp;index=10">The german speaking guy over here</a>, altough a bit more advanced, is explaining useful things too. He uses a button matrix out of an old chipcard terminal.</p>

<p>Personally my first experience with a button/keyboard matrix was the tiny 80s keyboard featured in <a href="/yamaha-ps-1/">one of my blog posts</a>. I found a lot of information about a similar keyboard on <a href="http://weltenschule.de/TableHooters/Yamaha_PS-2.html">this website</a>. The site owner even has put together a whole <a href="http://weltenschule.de/TableHooters/WarrantyVoidFAQ.htm">FAQ</a> about circuit bending and especially hacking keyboards. Scroll down a little (well a lot, it’s long) and look for headlines containing keyboard matrix. Deadly useful information there!!!</p>

<p>If it still all doesn’t add up, check <a href="http://pcbheaven.com/wikipages/How_Key_Matrices_Works/">this</a> and certainly <a href="https://en.wikipedia.org/wiki/Keyboard_matrix_circuit">wikipedia</a></p>

<h3 id="measuring">Measuring</h3>

<div class="pic_row_3">
  <div class="pic_left">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-03.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-03-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">The top 3 connections are labeled by a letter X, the bottom 4 with a letter Y. Ignore the red wire on the very bottom.</figcaption>
</figure>



  </div>
  <div class="pic_middle">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-04.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-04-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">No buttons pressed - no connections, but when button 1 is pressed X1 to Y1 show a connection.</figcaption>
</figure>



  </div>
  <div class="pic_right">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-05.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-05-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">X2 to Y1 is connected when button 2 is pressed</figcaption>
</figure>



  </div>
</div>

<div class="pic_row_3">
  <div class="pic_left">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-06.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-06-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">X3 to Y1 is connected when button 3 is pressed</figcaption>
</figure>



  </div>
  <div class="pic_middle">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-07.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-07-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">X1 to Y2 is connected when button 4 is pressed</figcaption>
</figure>



  </div>
  <div class="pic_right">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-08.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-08-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">X2 to Y2 is connected when button 5 is pressed</figcaption>
</figure>



  </div>
</div>

<p>I guess you see where this is going by now. If not, go back and rewatch the youtube videos an links posted <a href="#understanding">above</a>. Ok, so we can think of our matrix that it has 3 column lines, the X-wires, and 4 row lines, the Y-wires.</p>

<p><a name="housing"></a></p>
<h2 id="housing">Housing</h2>

<p>Before I started with writing code, I did some fitting to the case I was planning to put it in. I found this in my parent’s basement. Eventually I built it myself during my apprenticeship back in the 90ies. As far as I remember it should have become a battery powered radio and due to time reasons we never even started to build the electronics.</p>

<div class="pic_row_3">
  <div class="pic_left">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-09.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-09-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">These holes should have been the outlet for the speaker's sound.</figcaption>
</figure>



  </div>
  <div class="pic_middle">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-10.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-10-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">On the inside we had to construct this battery holder. Won't use it but won't remove it, it's glued in there and seems pretty steady.</figcaption>
</figure>



  </div>
  <div class="pic_right">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-11.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-11-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">The keypad should sit on top of it, the MC inside the box.</figcaption>
</figure>



  </div>
</div>

<div class="pic_row_3">
  <div class="pic_left">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-12.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-12-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">It just fits's perfectly on top of it. How nice is that? At first I thought I have to remove the boxes lid and couldn't think of a possibility to then steadily mount the keypad, but after some head-scratching I had a better idea...</figcaption>
</figure>



  </div>
  <div class="pic_middle">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-13.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-13-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">I replaced the original wires with new ones, but soldered them to the PCB upside-down, so they take as little space as possible underneath the keypad's PCB</figcaption>
</figure>



  </div>
  <div class="pic_right">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-15.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-15-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">The wires should be slipping into the speaker holes, so the PCB can be sticked to the box with hot-glue. The double-sided scotch tape was kind of a proof of concept.</figcaption>
</figure>



  </div>
</div>

<div class="pic_row_3">
  <div class="pic_left">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-16.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-16-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">Bougth these to be able to steadily close the lid. Lost the original ones or never had them.</figcaption>
</figure>



  </div>
  <div class="pic_middle">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-18.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-18-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">Redrilled and used this handy tool, out of my girlfriend's stash, to make the screws fit and the screw-heads even with the housing again.</figcaption>
</figure>



  </div>
  <div class="pic_right">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-19.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-19-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">Et voila, finally the box can be properly closed.</figcaption>
</figure>



  </div>
</div>

<p><a name="coding"></a></p>
<h2 id="writing-code">Writing code</h2>
<p><a name="breadboarding"></a></p>
<h3 id="breadboarding">Breadboarding</h3>

<div class="pic_row_3">
  <div class="pic_left">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-20.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-20-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">Soldered a pin-header to an Arduino Nano. Didn't use the double-row header, so it still fits into the breadboard!</figcaption>
</figure>



  </div>
  <div class="pic_middle">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-21.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-21-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">The 3 X wires (cols) and the 4 Y wires (rows) connected to the breadboard.</figcaption>
</figure>



  </div>
  <div class="pic_right">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-22.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-22-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">Digital pins 6-8 used as outputs (cols, X), digital pins 9-12 used as inputs (rows, Y). Some 10-15k pull-down resistors to keep LOW level when no buttons are pressed.</figcaption>
</figure>



  </div>
</div>

<div class="pic_row_3">
  <div class="pic_left">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-23.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-23-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">Much later on I decided to get rid of the pull-down resistors by making everything low-active. More on that further below...</figcaption>
</figure>



  </div>
  <div class="pic_middle">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-24.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-24-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">Had to fix the matrix. For some reason in the last row, two pins were not connected as I supposed they would be (* and 0).</figcaption>
</figure>



  </div>
  <div class="pic_right">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-25.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-25-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">Removed the jumper pin-header that used to be here. It could be set/unset to change the phones behaviour. I just hard-wired it to stay closed.</figcaption>
</figure>



  </div>
</div>

<p><a name="prerequisites"></a></p>
<h3 id="prerequisites">Prerequisites</h3>

<p>I won’t copy tons of code to here but leave it on github and post links to commits/diffs and whole code checkouts for copying and pasting.</p>

<p>I use some libraries because they make sense. They can be installed from the Arduino IDE “Library Manager”.</p>

<ul>
  <li><a href="https://github.com/klenov/advancedSerial">advancedSerial</a> - helps with debugging over the serial monitor, I think the original serial print and println commands are pretty uncomfortable to use.</li>
  <li><a href="https://github.com/FortySevenEffects/arduino_midi_library">MIDI</a> - send and/or receive MIDI messages via any serial port.</li>
</ul>

<p><a name="test-sketches"></a></p>
<h3 id="test-sketches">Test sketches</h3>

<p>Let’s check if the matrix and our breadboarding setup works and we actually understand what we are doing here with this <a href="https://github.com/JOJ0/matrixmidi/blob/e61bf0bfa955ecbeaa0f45649f630d2f4a837dd8/matrixmidi.ino">test sketch</a>. Manually set one of the output pins to HIGH level in <a href="https://github.com/JOJ0/matrixmidi/blob/e61bf0bfa955ecbeaa0f45649f630d2f4a837dd8/matrixmidi.ino#L36">lines 36-38</a> of the program and see what happens on the serial monitor.</p>

<p>With this next <a href="https://github.com/JOJ0/matrixmidi/commit/649d310613c5f7053b0462e370348ab6383cd295">commit</a> I loop through the 3 outputs, set them HIGH, and see which of the input lines have received the HIGH (because a button was pressed). <a href="https://github.com/JOJ0/matrixmidi/blob/649d310613c5f7053b0462e370348ab6383cd295/matrixmidi.ino">This is the whole file</a> to copy and paste. Actually this <em>is</em> the whole magic about reading out the state of any matrix keypad.</p>

<p>You should see something like that on the serial monitor when pressing buttons. It tells you wich row and col IDs are HIGH at the moment:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yes it's high: 0 0
...
...
yes it's high: 2 3
</code></pre></div></div>

<p><a name="best-practices"></a></p>
<h3 id="best-practices">Best practices</h3>

<p>Read through the commit messages and the comments in the code to see what I was thinking</p>

<ul>
  <li><a href="https://github.com/JOJ0/matrixmidi/commit/3b36122b84b1c1b27c1aff672218007e9224d779">store MIDI CCs in button array</a></li>
  <li><a href="https://github.com/JOJ0/matrixmidi/commit/9aeb3cf3a18c0cc44bb9d08b36ea99aa61b96d16">3 different modes</a> - my suggestion on how to easily switch between software emulated MIDI, just debugging and “real” MIDI. Helps with going back to coding and extending your controller later on without thinking to much.</li>
  <li><a href="https://github.com/JOJ0/matrixmidi/commit/1ee5c8eafd26eca593e37ddc5b05adf1b8383ceb">momentary press behaviour</a> - I decided to program my controller so it sends out what is called a “momentary press”. It sends out a MIDI CC on message when a button is pressed and does nothing as long as you keep that button pressed. Only on releasing the button it sends out a MIDI CC off message.</li>
  <li><a href="https://github.com/JOJ0/matrixmidi/commit/e7e280385e51e6e84102fbd30dbe0be340a570bf">set debounce time</a> - these values worked for me, a button press feels pretty responsive.</li>
  <li><a href="https://github.com/JOJ0/matrixmidi/commit/1f7ab8fb1a191fe1666f7917fff8126dbe7dbf33">make it low-active</a> - saves the pull-down resistors. This is the final version for a native MIDI version. Read on, for a solution to make it work on any Non-USB-MIDI compliant Arduino. If you want to use the hairless MIDI bridge software, just change the mode to 1 <a href="https://github.com/JOJ0/matrixmidi/blob/1f7ab8fb1a191fe1666f7917fff8126dbe7dbf33/matrixmidi.ino#L10">here</a></li>
</ul>

<p><a name="finalizing"></a></p>
<h2 id="finalizing">Finalizing</h2>

<h3 id="mounting-the-keypad-to-the-case">Mounting the keypad to the case</h3>

<div class="pic_row_3">
  <div class="pic_left">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-27.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-27-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">The hot-glue idea went back to be double-sided scotch tape. I found this so-called mounting-tape somewhere and thought I give it a try.</figcaption>
</figure>



  </div>
  <div class="pic_middle">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-28.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-28-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">I used two layers of tape, except on the places where the wires are. I guessed that they'd need about 1 layer of thickness.</figcaption>
</figure>



  </div>
  <div class="pic_right">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-29.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-29-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">Well, in the right half of the case where the 4 row wires are, I messed it up a little, there should have been only 1 layer of tape. Looks and feels pretty steady anyway.</figcaption>
</figure>



  </div>
</div>

<p><a name="usb-midi"></a></p>
<h3 id="the-cheapest-usb-midi-arduino-available">The cheapest USB-MIDI-Arduino available</h3>

<p>As mentioned at the very <a href="#top">top</a> of this post, most Arduinos are not capable of showing up as proper MIDI device in your computer’s operating system. If you are fine with using a software MIDI bridge like the <a href="http://projectgus.github.io/hairless-midiserial/">hairless MIDI bridge</a>, just look at the first picture in this chapter and you are done.</p>

<p>If it is not, one of the cheapest solutions around is to steal the electronics out of a USB to MIDI Adapter cable. You can get them in Europe for about 7-10 €. Certainly if you order them in China, a few pieces of them will cost you almost nothing. And btw: These cheap adapter cables are pretty useless for serious MIDI applications like controlling a synth from your your DAW. They are built so cheap, they literally loose data! Believe me, I measured it. But they are definitely good enough to be used for sending some knob or button movement aka some MIDI CC bytes. That’s only a tiny amount of data and my experience is that they handle that savely.</p>

<div class="pic_row_3">
  <div class="pic_left">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-30.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-30-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">I decided to use a fresh Arduino Nano, solder the wires directly to it and keep the pin-headered Nano for breadboarding purposes. The 7 keypad wires are connected to digital pins, the USB port transports power and serial data. This is the final software simulated MIDI variant.</figcaption>
</figure>



  </div>
  <div class="pic_middle">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-31.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-31-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">To make the Nano a fully fledged USB-MIDI device I'll (mis)use this cheap USB-MIDI adapter cable.</figcaption>
</figure>



  </div>
  <div class="pic_right">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-33.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-33-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">It could be easily opened by poking around on the edges with a screwdriver. Some versions of these adapter cables are easier to forcefully open than other's ;-) Good luck with yours!</figcaption>
</figure>



  </div>
</div>

<div class="pic_row_3">
  <div class="pic_left">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-34.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-34-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">This is where the MIDI-in and MIDI-out DIN jacks are connected. We are interested in the wires that connect the MIDI-INPUT port: IN- (black) and GND (red). Now please don't ask me why they chose to use a red wire for GND!?!</figcaption>
</figure>



  </div>
  <div class="pic_middle">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-36.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-36-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">Original wires desoldered and hooked up to the Nano. Green wire: Nano TX1 to Adapter-PCB IN-, black wire: Nano GND to Adapter-PCB GND. Now recap the signal path when a button is pressed: Arduino sends OUT (TX1) data INTO (IN-) the adapter thing. ...</figcaption>
</figure>



  </div>
  <div class="pic_right">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-37.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-37-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">... The adapter thing sends the data INTO the computers USB port. Makes sense? If your chosen case allows it, leave the USB side connected as is. ...</figcaption>
</figure>



  </div>
</div>

<div class="pic_row_3">
  <div class="pic_left">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-39.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-39-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">... In my case I had to desolder it to nicely bring it into the case. I also reused the original strain relief plastic thing. Had to cut it a little to get it into my boxes hole.</figcaption>
</figure>



  </div>
  <div class="pic_middle">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-41.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-41-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">Soldered on four fresh wires of the same color to the PCB. Note that I chose the opposite direction for my solder joints as it originally was. Helps when putting in the whole PCB into a bag for isolation.</figcaption>
</figure>



  </div>
  <div class="pic_right">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-42.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-42-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">Checking if everything still would fit in. Only thing left to do is connecting the four wires to the USB-cable</figcaption>
</figure>



  </div>
</div>

<div class="pic_row_3">
  <div class="pic_left">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-43.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-43-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">Decided to connect the red 5V wire of the Adapter-PCB directly to the Arduino's VIN pin first, ...</figcaption>
</figure>



  </div>
  <div class="pic_middle">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-44.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-44-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">... and then via the 5V pin to the USB cable's red wire (V+, Vss). The attentive reader now would say that it would be more logic if I would've exchanged VIN and 5V on the Arduino. Well, that's true, but in the end 5V and VIN are exactely the same :-)</figcaption>
</figure>



  </div>
  <div class="pic_right">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-45.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-45-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">Finally soldering all the freshly hooked on wires from the Adapter-PCB's USB-side to the original USB-cable again (and certainly the red wire coming from Nano 5V pin I just mentioned).</figcaption>
</figure>



  </div>
</div>

<div class="pic_row_3">
  <div class="pic_left">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-46.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-46-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">Isolating the solder joints with shrink tube.</figcaption>
</figure>



  </div>
  <div class="pic_middle">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-47.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-47-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">Mounting it together. We are looking good, but I forgot a couple of things so I had to reopen it ;-)</figcaption>
</figure>



  </div>
  <div class="pic_right">
  </div>
</div>

<p><a name="testrun"></a></p>
<h3 id="testrun">Testrun</h3>

<p>Now that we don’t have to use the hairless MIDI bridge anymore, we change the mode of the program to send native MIDI speed (31250 bps) out of the Arduinos TX1 pin:</p>

<p><a href="https://github.com/JOJ0/matrixmidi/blob/master/matrixmidi.ino#L9">Line 9</a></p>

<div class="pic_row_3">
  <div class="pic_left">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-48.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-48-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">Flashing the final program to the fresh Arduino via the black USB cable connected to the original Arduino's USB port. Notice that the silver USB cable is not connected to the computers's USB-port at this moment because I think it's not a good idea if two power sources were connected at once. So watch out!!!</figcaption>
</figure>



  </div>
  <div class="pic_middle">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-49.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-49-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">That's when I relized that the red power LED's of the Arduino and the Adapter-PCB are shining through the orange case heavily. Nice!</figcaption>
</figure>



  </div>
  <div class="pic_right">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-50.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-50-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">Left is the Adapter-PCB's LED and right the Arduino's tiny but pretty bright SMD-LED. This certainly brings up new ideas...</figcaption>
</figure>



  </div>
</div>

<!-- If a width is specified, most probably the video should be displayed "inline", thus disable margins -->

<div class="outer_ytcontainer" style="margin-top: 6px;">

  <div class="ytcontainer">
    <iframe class="yt" allowfullscreen="" src="https://www.youtube.com/embed/C4flMBFiFPc"></iframe>
  </div>
</div>

<p>The Nano’s onboard LEDs and the Adapter-PCB’s MIDI-IN LED should blink shortly when MIDI data is transmitted from the controller.
<br /><br /></p>

<p><a name="din-midi"></a></p>
<h3 id="but-what-if-i-just-want-to-use-a-classic-midi-cable">But what if I just want to use a classic MIDI cable?</h3>

<p>Just connect GND, +5V and TX1 pins of the Arduino to a 5-pin DIN-socket like described <a href="https://learn.sparkfun.com/tutorials/midi-tutorial/hardware--electronic-implementation">in this sparkfun tutorial.</a></p>

<p><a href="https://cdn.sparkfun.com/assets/learn_tutorials/4/0/8/midihw.gif">The drawing on the bottom of this pic</a> shows where the pins of your DIN jack should go:</p>

<ul>
  <li>pin 4 -&gt; 220R resistor -&gt; +5V</li>
  <li>pin 5 -&gt; 220R resistor -&gt; Arduino TX1</li>
  <li>pin 2 -&gt; cable shield -&gt; Arduino GND</li>
</ul>

<p>As you’d expect, just use an ordinary MIDI cable (jack-jack) to connect from your controller’s socket to the device you want to control.</p>

<p><a name="fancy"></a></p>
<h3 id="making-it-even-fancier">Making it even fancier</h3>

<p>I had 5 digital pins left on the Arduino Nano, let’s use them!</p>

<div class="pic_row_3">
  <div class="pic_left">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-51.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-51-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">One 2,2k resistor hooked up to GND will be used to limit current for 5 white LEDs.</figcaption>
</figure>



  </div>
  <div class="pic_middle">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-52.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-52-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">Connecting the resistor with 5 wires going to the LEDs cathode pins.</figcaption>
</figure>



  </div>
  <div class="pic_right">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-53.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-53-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">Soldering together this amount of wires sometimes is a bit challenging but if you just do it once and make sure you would never have to resolder this exact joint, IMHO it's an OK solution.</figcaption>
</figure>



  </div>
</div>

<div class="pic_row_3">
  <div class="pic_left">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-54.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-54-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">Shrink tube for isolation.</figcaption>
</figure>



  </div>
  <div class="pic_middle">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-55.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-55-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">The 5 white LEDs connected to the resistor (hidden in the shadows and shrink-tubed already). Orange wires are, you guessed it, the LEDs anodes, ...</figcaption>
</figure>



  </div>
  <div class="pic_right">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-56.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-56-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">... which were connected to the 5 remaining digital pins (D1-D5).</figcaption>
</figure>



  </div>
</div>

<div class="pic_row_3">
  <div class="pic_left">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-57.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-57-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">Alright, it's getting packed in there ;-)</figcaption>
</figure>



  </div>
  <div class="pic_middle">
  </div>
  <div class="pic_right">
  </div>
</div>

<p><a name="addon"></a></p>
<h4 id="blink-on-send-addon">Blink on send addon</h4>

<p>Just a little addition to the code: <a href="https://github.com/JOJ0/matrixmidi/commit/58210e59dabe624c4fe28c8a071a0a85428c7f11">blink 5 LEDs when sending CC</a></p>

<!-- If a width is specified, most probably the video should be displayed "inline", thus disable margins -->

<div class="outer_ytcontainer" style="width: 100%; margin-top:0 auto; margin-left:0 auto; margin-right:0 auto">

  <div class="ytcontainer">
    <iframe class="yt" allowfullscreen="" src="https://www.youtube.com/embed/4g5KznbCrjw"></iframe>
  </div>
</div>

<p>Maybe using red LEDs would bring a more dramatic effect.
<br /><br /></p>

<div class="clearfix">
    


<figure class="sidebyside" style="width: 49%; float: left; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-58.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-58-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">No buttons pressed</figcaption>
</figure>



    


<figure class="sidebyside" style="width: 49%; float: right; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-59.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-59-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">Any button is pressed - At the moment the white LEDs are hanging around loosely in the case, sticking them closely to the cases edges with some tape probably would help to let them shine through better.</figcaption>
</figure>



</div>

<p><a name="final"></a></p>
<h2 id="the-final-product">The final product</h2>

<div class="pic_row_3">
  <div class="pic_left">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-60.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-60-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">Happy with the thing.</figcaption>
</figure>



  </div>
  <div class="pic_middle">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-61.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-61-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">I really dig it's small size.</figcaption>
</figure>



  </div>
  <div class="pic_right">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-17-midictrl1/matrixmidi-62.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-17-midictrl1/matrixmidi-62-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;">Compared to an already small Korg Volca Beats. The lila thing bottom right is another controller I built, it will be featured in a future post.</figcaption>
</figure>



  </div>
</div>

<p><a name="using"></a></p>
<h2 id="using-it">Using it</h2>

<!-- If a width is specified, most probably the video should be displayed "inline", thus disable margins -->

<div class="outer_ytcontainer" style="margin-top: 6px;">

  <div class="ytcontainer">
    <iframe class="yt" allowfullscreen="" src="https://www.youtube.com/embed/sDhxnpLm9js"></iframe>
  </div>
</div>

<p>MIDI mapping in Ableton Live - The momentary-mode buttons behave differently depending on which controls they are mapped to:</p>
<ul>
  <li>(mis)using buttons for dial type controls: as long as the button is pressed the dial is put to halfway up (we send MIDI CC value 64), when releasing it goes to 0 again.</li>
  <li>on/off controls like eg the mute buttons: as long as the button is pressed it’s unmuted, if released it’s muted again. For device on/off buttons the behaviour is the same.</li>
  <li>the solo buttons behaviour is different: press once - solo stays on - press again - solo stays off</li>
</ul>

<p><a name="supplies"></a></p>
<h2 id="getting-supplies">Getting supplies</h2>

<p>As usual I recommend supporting and buying from musikding.de, because it’s just well sorted and has good prices (first two links). For the MIDI adapter cables and Arduinos I have put together some links to cheap buys on amazon.de. If you like what you see on this blog please support me by using these links. I get a little nothing from amazon then ;-)</p>

<ul>
  <li><a href="https://www.musikding.de/14-Pin-strip">14 pin strip</a></li>
  <li><a href="https://www.musikding.de/Aluminium-enclosure-Coloured">nice colored cases</a></li>
  <li><a href="https://www.amazon.de/gp/product/B01FFIFA3S/ref=as_li_tl?ie=UTF8&amp;tag=j0j0sblog-21&amp;camp=1638&amp;creative=6742&amp;linkCode=as2&amp;creativeASIN=B01FFIFA3S&amp;linkId=80418c9799c2a20d2f5b080ad4dda710">USB-MIDI Adapter cable 7€</a></li>
  <li><a href="https://www.amazon.de/gp/product/B01J7N6EGO/ref=as_li_tl?ie=UTF8&amp;tag=j0j0sblog-21&amp;camp=1638&amp;creative=6742&amp;linkCode=as2&amp;creativeASIN=B01J7N6EGO&amp;linkId=ad4cf92e2bfc2f439296cdd0ef072639">USB-MIDI Adapter cable 11€</a></li>
  <li><a href="https://www.amazon.de/gp/product/B07KLSYVX9/ref=as_li_tl?ie=UTF8&amp;tag=j0j0sblog-21&amp;camp=1638&amp;creative=6742&amp;linkCode=as2&amp;creativeASIN=B07KLSYVX9&amp;linkId=5b901e1c5b237185c8051dabb10b1ba7">USB-MIDI Adapter cable 4€</a></li>
  <li><a href="https://www.amazon.de/gp/product/B07K16G37V/ref=as_li_tl?ie=UTF8&amp;tag=j0j0sblog-21&amp;camp=1638&amp;creative=6742&amp;linkCode=as2&amp;creativeASIN=B07K16G37V&amp;linkId=f200b2f7792c16d3bbaba9637330cc19">USB-MIDI Adapter cable 5€</a></li>
  <li><a href="https://www.amazon.de/gp/product/B079WKW8VL/ref=as_li_tl?ie=UTF8&amp;tag=j0j0sblog-21&amp;camp=1638&amp;creative=6742&amp;linkCode=as2&amp;creativeASIN=B079WKW8VL&amp;linkId=e7d19b5a962e7f3bb9d8ba4b5849f198">USB-MIDI Adapter cable 6€</a></li>
  <li><a href="https://www.amazon.de/gp/product/B007JIT9SU/ref=as_li_tl?ie=UTF8&amp;tag=j0j0sblog-21&amp;camp=1638&amp;creative=6742&amp;linkCode=as2&amp;creativeASIN=B007JIT9SU&amp;linkId=136d921ef65f820158ad51771e8fa097">USB-MIDI Adapter cable 12€</a></li>
  <li><a href="https://www.amazon.de/gp/product/B074MZSJ2V/ref=as_li_tl?ie=UTF8&amp;tag=j0j0sblog-21&amp;camp=1638&amp;creative=6742&amp;linkCode=as2&amp;creativeASIN=B074MZSJ2V&amp;linkId=2fc5ec0c6b557d5ae75fd07aa64f545e">USB-MIDI Adapter cable 8€</a></li>
  <li><a href="https://www.amazon.de/gp/product/B07KJCK9GT/ref=as_li_tl?ie=UTF8&amp;tag=j0j0sblog-21&amp;camp=1638&amp;creative=6742&amp;linkCode=as2&amp;creativeASIN=B07KJCK9GT&amp;linkId=1dd25361f4040a07656dc8e94e887850">USB-MIDI Adapter cable 7€</a></li>
  <li><a href="https://www.amazon.de/gp/product/B0713ZRJLC/ref=as_li_tl?ie=UTF8&amp;tag=j0j0sblog-21&amp;camp=1638&amp;creative=6742&amp;linkCode=as2&amp;creativeASIN=B0713ZRJLC&amp;linkId=8c6fee6ea89917881b4feae113037aa9">3 x Arduino Nano 14€</a></li>
  <li><a href="https://www.amazon.de/gp/product/B072XS9ZTX/ref=as_li_tl?ie=UTF8&amp;tag=j0j0sblog-21&amp;camp=1638&amp;creative=6742&amp;linkCode=as2&amp;creativeASIN=B072XS9ZTX&amp;linkId=37e1b95042e98eaad5cf77d242313076">3 x Arduino Nano 15€</a></li>
  <li><a href="https://www.amazon.de/gp/product/B07F6XGC7L/ref=as_li_tl?ie=UTF8&amp;tag=j0j0sblog-21&amp;camp=1638&amp;creative=6742&amp;linkCode=as2&amp;creativeASIN=B07F6XGC7L&amp;linkId=876cfebcde6c55e946268dd4aa5b34e9">5 x Arduino Nano 19€</a></li>
  <li><a href="https://www.amazon.de/gp/product/B072LPHG92/ref=as_li_tl?ie=UTF8&amp;tag=j0j0sblog-21&amp;camp=1638&amp;creative=6742&amp;linkCode=as2&amp;creativeASIN=B072LPHG92&amp;linkId=6ca6f04ce04f6a8ef63772839e34e794">5 x Arduino Nano 17€</a></li>
  <li><a href="https://www.amazon.de/gp/product/B078S8BJ8T/ref=as_li_tl?ie=UTF8&amp;tag=j0j0sblog-21&amp;camp=1638&amp;creative=6742&amp;linkCode=as2&amp;creativeASIN=B078S8BJ8T&amp;linkId=4d050b49e9f6c69e4e2dab0fd2679b8a">5 x Arduino Nano 18€</a></li>
  <li><a href="https://www.amazon.de/gp/product/B078SBBST6/ref=as_li_tl?ie=UTF8&amp;tag=j0j0sblog-21&amp;camp=1638&amp;creative=6742&amp;linkCode=as2&amp;creativeASIN=B078SBBST6&amp;linkId=00815dcc067cab8eb8eb90c1df2e03a6">3 x Arduino Nano 10€</a></li>
  <li><a href="https://www.amazon.de/gp/product/B01LWSJBTD/ref=as_li_tl?ie=UTF8&amp;tag=j0j0sblog-21&amp;camp=1638&amp;creative=6742&amp;linkCode=as2&amp;creativeASIN=B01LWSJBTD&amp;linkId=1b9723a7a8427d35ceef87802127f732">1 x Arduino Nano 6€</a></li>
  <li><a href="https://www.amazon.de/gp/product/B07C4J3PKT/ref=as_li_tl?ie=UTF8&amp;tag=j0j0sblog-21&amp;camp=1638&amp;creative=6742&amp;linkCode=as2&amp;creativeASIN=B07C4J3PKT&amp;linkId=1a6bc9792c4f6b906a084d2a05b299ae">5 x Arduino Nano 12€</a></li>
</ul>]]></content><author><name></name></author><summary type="html"><![CDATA[MIDI controllers are not the most complicated things on earth to build and program.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.jojotodos.net/images/2018-11-17-midictrl1/matrixmidi-47-th.jpg" /><media:content medium="image" url="https://blog.jojotodos.net/images/2018-11-17-midictrl1/matrixmidi-47-th.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">The Charger Tape</title><link href="https://blog.jojotodos.net/charger-tape/" rel="alternate" type="text/html" title="The Charger Tape" /><published>2018-11-03T00:00:00+00:00</published><updated>2018-11-03T00:00:00+00:00</updated><id>https://blog.jojotodos.net/charger-tape</id><content type="html" xml:base="https://blog.jojotodos.net/charger-tape/"><![CDATA[<p>Alright, let’s do something boring: Building a battery charger. So why would you do that? I don’t have any idea, just go buy one! ;-) But apparently I had a reason to build one myself.</p>

<p>Some time ago I built a couple of rechargeable button-cell-battery-packs which are featured in <a href="/das-adhs/#building-7-segment">this post</a><br />After trying to recharge one of them with an old NiCd fast-charger I learned the hard way how my batteries actually look from the inside:</p>

<div class="pic_row_3">
  <div class="pic_left">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-3-charger-tape/ChrgTpExpl-01.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-3-charger-tape/ChrgTpExpl-01-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;"></figcaption>
</figure>



  </div>
  <div class="pic_middle">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-3-charger-tape/ChrgTpExpl-02.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-3-charger-tape/ChrgTpExpl-02-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;"></figcaption>
</figure>



  </div>
  <div class="pic_right">
    


<figure class="sidebyside" style="width: ; float: ; margin: ; ">
  <a href="/images/2018-11-3-charger-tape/ChrgTpExpl-03.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-3-charger-tape/ChrgTpExpl-03-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;"></figcaption>
</figure>



  </div>
</div>

<p>Don’t try this at home kids!</p>

<p>So far so good, I didn’t burn my flat yet, so I decided to either buy or build a charger that is designed to charge Nickel-Metal Hybride (NiMH) batteries with very little capacity.</p>

<h2 id="what-you-always-wanted-to-know-about-rechargeable-batteries">What you always wanted to know about rechargeable batteries</h2>

<p>First off, my tiny button cell accumulators have the following specs:</p>

<ul>
  <li>1,2 V (exactely the same as normal AA, AAA, etc. rechargable batteries;
this value is nominal, in reality most of them have a little more, something like 1,3 to 1,45 when fully charged)</li>
  <li>80 mAh (<a href="https://whatis.techtarget.com/definition/milliampere-hour-mAh">milliampere hours</a>) capacity</li>
</ul>

<p>In short: They are ordinary rechargeable batteries and it actually should be save to load them with an ordinary charger.</p>

<p>So why did my test-candidate explode then?</p>

<p>It was simply overcharged. NiMH cells are designed to be only fast-charged until they reach their full capacity. After that, keeping them connected to high current results in a lot of heat and…you saw the pics.</p>

<p>So either the charger has thermal sensors to shut off before overheating, or it just uses a low current the cell can withstand for a longer (infinite) time duration.</p>

<p>Sensoring seemed tedious so I decided to build a low current charger.</p>

<p>A safe current for NiMH cells is 1/10 of their capacity (1/10 C) or even less. In my batteries case this would be 1/10 * 80 = 8mA. There you have it: No affordable charger on the market seems to handle such a low current. Typically chargers go as low as 150 mA, which is fine for typical batteries which have a capacity of 1500 mAh to 2500 mAh (or even more), but not for my tiny 80 mAh cells.</p>

<h2 id="finding-and-customizing-a-circuit-design">Finding and customizing a circuit design</h2>
<p><a name="finding"></a></p>

<p>Some googling and studying charger designs brought up <a href="https://forum.allaboutcircuits.com/threads/constant-nimh-trickle-charger.14624/">this forum thread</a>. The schematic suggested by member SgtWookie seemed to be a perfect fit:</p>

<div class="clearfix">



<figure class="sidebyside" style="width: 100%; float: left; margin: ; ">
  <a href="/images/2018-11-3-charger-tape/ChrgTpSchem-01.jpg">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-3-charger-tape/ChrgTpSchem-01-th.jpg" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;"></figcaption>
</figure>



</div>

<p>It features two regulator ICs (TLV1117C): One limiting the current (U1) and the other one the voltage (U2). The battery(pack) is represented by capacitor C2 (he uses the similar-to-battery-behaviour of the capacitor for the software simulation). I substituted the two regulators with the more common and easy to get LM317 type.</p>

<ul>
  <li><strong>Charging voltage</strong> should be set slightly higher than the voltage of the fully charged battery pack. My two-cell packs have about 2 * 1,35 = 2,7 V so around <strong>2,8-2,9 V</strong> should be fine.
    <ul>
      <li>Fortunately the design already handles charging voltage for two-cell packs. It can be fine tuned using the <strong>trim-pot R5</strong>.</li>
      <li>measure between point A and ground</li>
    </ul>
  </li>
  <li><strong>Charging current</strong> as discussed above, not more than <strong>8 mA</strong>.
    <ul>
      <li>It is set by <strong>resistors R1,R2</strong> (On first sight it is slightly confusing that he uses 2 identical resistors in parallel. I suppose he did this to split the current  (and thus the power consumption) in half and spare the use of an R with higher power specs (more Watts - more expensive - not as common in ones components stash), I will use just one R as my current is very little compared to the 260 mA in the original design. Let’s just call my resistor R1 and forget about R2.).</li>
      <li>open circuit between points A and B and connect multimeter in between for measuring</li>
    </ul>
  </li>
</ul>

<p>If you have a look on pages 12 and 13 in the <a href="http://www.ti.com/lit/ds/symlink/lm317.pdf">LM317 datasheet</a> you will find examples for current and voltage limiting circuits that look almost identical to SgtWookies design. His circuit is basically a combination of two examples. Well done!</p>

<p>This is my final customized version. The 120k resistor R1 configures LM317_1 to limit charging current to 6mA, being even more healthy for my batteries than the discussed 8mA:</p>

<div class="clearfix">



<figure class="sidebyside" style="width: 100%; float: left; margin: ; ">
  <a href="/images/2018-11-3-charger-tape/ChrgTpSchem-02.png">
      <!-- if a collection for this page is existing, there must be thumbs named file-th.jpg-->
      
      <img src="/images/2018-11-3-charger-tape/ChrgTpSchem-02-th.png" alt="" />
      
  </a>
  <figcaption style="margin-bottom: 12px;"></figcaption>
</figure>



</div>

<h3 id="some-theory-for-the-geeks">Some theory for the geeks</h3>

<p>Skip this if it’s boring ;-) I’ll try to explain why in my case R2 surely is not necessary.</p>

<h4 id="r1-power-consumption---original-design">R1 power consumption - Original design</h4>

<p>Assuming R2 is missing:</p>

<p>The formula for calculating the power consumption of a device (eg. a resistor) is</p>

<p>P = V * I</p>

<p>The V on R1 is unknown so just calculate it using Ohm’s law:</p>

<p>V = R * I = 10 Ohm * 260 mA = 10 * 0,26 = 2,6 V</p>

<p>Now find out how much power R1 has to withstand:</p>

<p>P = V * I = 2,6 * 0,26 = 0,676 W (Watts)</p>

<p>The most common resistors support max power levels of 0,3 to 0,5 Watts. With splitting the current in half by using a second resistor R2 in parallel with R1, also the power consumption is halfed to 0,338 W for each R.</p>

<h4 id="r1-power-consumption---customized-design">R1 power consumption - Customized design</h4>

<p>V = R * I = 120 Ohm * 6 mA = 120 * 0,006 = 0,72 V</p>

<p>P = V * I = 0,72 * 0,006 = 0,00432 W = 4,3 mW</p>

<p>4,3 milliwatts is almost nothing and every resistor form factor I know of would withstand it. No need for splitting the current in half with a second R.</p>

<h4 id="how-long-does-it-take-to-load-then">How long does it take to load then?</h4>

<p>theoretically:</p>

<p>t = C / I = 80mAh / 6mA = 0,080 / 0,006 = 13,33 h</p>

<p>I -&gt; current in A<br />
C -&gt; capacity in Ah<br />
t -&gt; time in h</p>

<p>typically a loss of 30-40% has to be counted in, lets calc with 40%:</p>

<p>C = 0,080 + 40% = 0,080 * 1,4 = 0,112
t = C / A = 0,112 / 0,006 = 18,66 h</p>

<p>So let’s say a night and something. It should be safe to leave the charger connected for a couple of days.</p>

<p><br /></p>

<h2 id="giving-it-a-home">Giving it a home</h2>

<p>…and why it’s got its name. Click the thumbnails to zoom in and read short description.</p>

<div class="photo-gallery-frame clearfix">
  <ul class="photo-gallery-list">
    
    <li>
      <a href="/charger-tape/ChrgTpCase-01/" name="ChrgTpCase-01">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-01-th.jpg" alt="That's the idea: A cassette tape case should hold the circuit board and the battery to be charged." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-02/" name="ChrgTpCase-02">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-02-th.jpg" alt="Cutting a piece of stripboard..." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-03/" name="ChrgTpCase-03">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-03-th.jpg" alt="...and cleaning it with a file because it's old and otherwise it's not easy to solder to." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-04/" name="ChrgTpCase-04">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-04-th.jpg" alt="The piece is tightly fit into the case so it holds itself without glue. A perfect battery holder comes for free with the tape case :-)" />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-05/" name="ChrgTpCase-05">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-05-th.jpg" alt="Input connector from the 12V power supply on the left, battery connector output will be on the right." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-06/" name="ChrgTpCase-06">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-06-th.jpg" alt="Preparing the cable inlet with a saw, ..." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-07/" name="ChrgTpCase-07">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-07-th.jpg" alt="...gently clipping of some pieces, ..." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-08/" name="ChrgTpCase-08">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-08-th.jpg" alt="... finishing with a file, ..." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-09/" name="ChrgTpCase-09">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-09-th.jpg" alt="... and here we go!" />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-10/" name="ChrgTpCase-10">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-10-th.jpg" alt="Current regulator and input connector ..." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-11/" name="ChrgTpCase-11">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-11-th.jpg" alt="... soldered." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-12/" name="ChrgTpCase-12">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-12-th.jpg" alt="Input connector plug to the 12V supply." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-13/" name="ChrgTpCase-13">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-13-th.jpg" alt="The resistor that's configuring the LM317's constant current should be replaceable. Also configurations with 2 resistors in parallel would be possible." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-14/" name="ChrgTpCase-14">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-14-th.jpg" alt="The second regulator ..." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-15/" name="ChrgTpCase-15">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-15-th.jpg" alt="..., the 2 pieces of 3-pin-plugs for the resistor and on the right the trim-pot you'll see in the next pic." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-16/" name="ChrgTpCase-16">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-16-th.jpg" alt="There it is." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-17/" name="ChrgTpCase-17">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-17-th.jpg" alt="The 0,2 Ohms resistor. Certainly the 5 Watts are way overpowered, I just had this one at hand. Any common 0,25 Watts resistor will do." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-18/" name="ChrgTpCase-18">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-18-th.jpg" alt="Pin connectors can be easily bent with a flat-nose pliers to get a 90 degrees version." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-19/" name="ChrgTpCase-19">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-19-th.jpg" alt="The battery output connector and 2 more resistors. For R4 I didn't have a 240 Ohms resistor at hand, so I just used two 120's in series." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-20/" name="ChrgTpCase-20">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-20-th.jpg" alt="The 2 resistors and the output connector soldered (left is right and right is left! ;-))." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-21/" name="ChrgTpCase-21">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-21-th.jpg" alt="We are looking good." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-22/" name="ChrgTpCase-22">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-22-th.jpg" alt="Really dig the battery holder!" />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-23/" name="ChrgTpCase-23">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-23-th.jpg" alt="Yes I do! And now with cable going into from the supply." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-24/" name="ChrgTpCase-24">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-24-th.jpg" alt="When closed it holds together nicely, even though the battery prevents the lid from closing 100%. Still perfect I think." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-25/" name="ChrgTpCase-25">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-25-th.jpg" alt="The coupling capacitor. You'll see where it's connected later." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-26/" name="ChrgTpCase-26">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-26-th.jpg" alt="The missing links done with isolated wires. Left is the power connector side." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-27/" name="ChrgTpCase-27">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-27-th.jpg" alt="Zoomed in to the right side where the battery connector sits." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-28/" name="ChrgTpCase-28">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-28-th.jpg" alt="On the right, just before the battery connector I put a jumper to be able to open the circuit and hang in an ampere meter." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-29/" name="ChrgTpCase-29">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-29-th.jpg" alt="The jumper opened. Also you can see where the coupling capacitor is connected to." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-30/" name="ChrgTpCase-30">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-30-th.jpg" alt="The 120 Ohms resistor that configures the first LM317 regulator to limit charging current to about 6mA." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-31/" name="ChrgTpCase-31">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-31-th.jpg" alt="The solder-side finished with all the missing link wires. The black dots mark the strips that need ground connection, wired together with black wires." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-32/" name="ChrgTpCase-32">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-32-th.jpg" alt="" />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-33/" name="ChrgTpCase-33">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-33-th.jpg" alt="Fine tuning the charging voltage with the trim-pot. This has to be done without load - no battery connected. The battery packs reach a max of 2.7 V, so 2.9 is about right." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-34/" name="ChrgTpCase-34">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-34-th.jpg" alt="Putting an ampere meter into the circuit to check the charging current, regulator #1 (plus the 120 Ohms resistor) produces. This has to be measured with the load - the battery pack - connected." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-35/" name="ChrgTpCase-35">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-35-th.jpg" alt="5.6 mA will definitely never overload my tiny batteries again." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-36/" name="ChrgTpCase-36">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-36-th.jpg" alt="Another neat feature added: Connectors for regular 2-cell-battery-holders, ..." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-37/" name="ChrgTpCase-37">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-37-th.jpg" alt="... or button-cell-packs that don't have the special 4-pin connector." />
      </a>
    </li>
    
    <li>
      <a href="/charger-tape/ChrgTpCase-38/" name="ChrgTpCase-38">
        <img src="/images/2018-11-3-charger-tape/ChrgTpCase-38-th.jpg" alt="Ampere meter connections via the jumper is certainly still possible with this setup. Unbelievable feature madness here, right? haha ;-)" />
      </a>
    </li>
    
  </ul>
</div>

<h3 id="materials">Materials</h3>

<p><a href="https://www.musikding.de/LM317T_1">LM317 regulator</a><br /></p>

<p>Those are for building power and battery connector plugs:<br />
<a href="https://www.musikding.de/10-Pin-strip">10 pin strip (for 4-pin battery connector and 5-pin power supply connector </a><br /></p>

<p>Unfortunately musikding.de doesn’t have the female ones in stock.</p>

<p>Take <a href="https://www.musikding.de/20-Pin-inline-socket">these 20 pin inline sockets</a> for the resistor connector and the additional regular-battery-holder connector. They are also called transistor-sockets. Keep in mind that they have small holes. Above pin strips won’t fit together with them!<br /></p>

<p>These are some combination packs with headers and sockets that fit together. It’s Amazon affiliate links. Click them if you like what you read, I get a tiny percentage of what you bought then. Thanks!<br />
<a href="https://www.amazon.de/gp/product/B07DBY753C/ref=as_li_tl?ie=UTF8&amp;tag=j0j0sblog-21&amp;camp=1638&amp;creative=6742&amp;linkCode=as2&amp;creativeASIN=B07DBY753C&amp;linkId=26f59e1905e3966e977df01c751fb19b">30 pieces pin headers and sockets pack</a><br />
<a href="https://www.amazon.de/gp/product/B01MDRPUFU/ref=as_li_tl?ie=UTF8&amp;tag=j0j0sblog-21&amp;camp=1638&amp;creative=6742&amp;linkCode=as2&amp;creativeASIN=B01MDRPUFU&amp;linkId=663f34d1fe525181873e33ab18d75570">60 pieces pin headers and sockets pack</a><br />
<a href="https://www.amazon.de/gp/product/B078SQ1CZF/ref=as_li_tl?ie=UTF8&amp;tag=j0j0sblog-21&amp;camp=1638&amp;creative=6742&amp;linkCode=as2&amp;creativeASIN=B078SQ1CZF&amp;linkId=d296266c2f48d9a38d224eaa07455123">40 pieces pin headers and sockets pack</a><br /></p>

<p>For resistors buy anything, anywhere. I like <a href="https://www.musikding.de/Metal-Film-06W">Metal Film types</a>, they are quite cheap but can stand about 0,6 Watts, which is a little more than the most common ones with 0,25 Watts (I think they are called carbon-layer). You won’t need higher power resistors for this project but it’s good to have some in the stash.</p>

<p>The power supply can be almost anything you have lying around. It should deliver a minimum of 6V, I think the LM317 needs this, maybe it works with a 5V one. The absolute maximum input voltage for this IC is up to 30V, so you have a wide range of choices between these values.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Alright, let’s do something boring: Building a battery charger. So why would you do that? I don’t have any idea, just go buy one! ;-) But apparently I had a reason to build one myself.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.jojotodos.net/images/2018-11-3-charger-tape/ChrgTpCase-22-th.jpg" /><media:content medium="image" url="https://blog.jojotodos.net/images/2018-11-3-charger-tape/ChrgTpCase-22-th.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>