<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title></title>
 <link href="/" rel="self"/>
 <link href=""/>
 <updated>2026-06-10T19:03:28+00:00</updated>
 <id></id>
 <author>
   <name></name>
   <email></email>
 </author>

 
 <entry>
   <title>Making local LLM fast</title>
   <link href="/programming/2026/06/10/making-local-llm-fast.html"/>
   <updated>2026-06-10T00:00:00+00:00</updated>
   <id>/programming/2026/06/10/making-local-llm-fast</id>
   <content type="html">&lt;p&gt;I built a tool called &lt;a href=&quot;https://github.com/bogdanr/fono&quot;&gt;Fono&lt;/a&gt;. It’s a voice front-end for your computer that can run entirely on your own machine. No cloud, no account, no audio leaving the laptop. It has three jobs, on two hotkeys:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Hold F7 to dictate&lt;/strong&gt; and cleaned-up text lands in whatever window you were typing in.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Hold F8 to talk to an assistant&lt;/strong&gt; and it answers various thinkgs. It can also call tools (look at what’s on your screen, and more to come) to actually do things, not just reply.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Give your computer a voice.&lt;/strong&gt; Coding agents or other tools can speak to you through it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first two jobs can lean on a local language model. The problem is that a local model has to think before it speaks, and that feels slow in a way a cloud API running on a rack of GPUs does not. On my laptop, the very first assistant turn was taking almost three seconds before a single word came back. By the sixth turn of a conversation it was closer to seven. That’s death by a thousand milliseconds. It makes the whole thing feel broken even when it’s working perfectly.&lt;/p&gt;

&lt;p&gt;This post is the story of getting that first word out in about a third of a second instead. I will explain what actually costs the time, show you the bug I made (it’s a good one) and give you the exact commands to reproduce everything on your own hardware. I don’t do “trust me bro” benchmarks :)&lt;/p&gt;

&lt;h3 id=&quot;what-actually-takes-the-time&quot;&gt;What actually takes the time&lt;/h3&gt;

&lt;p&gt;When you send a prompt to a local model, the work splits into two very different phases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prefill&lt;/strong&gt; is the model reading your prompt. Every token (every chunk of text) gets pushed through the neural network so the model “understands” the context before it responds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Decode&lt;/strong&gt; is the model answering. You watch this happen, word by word.&lt;/p&gt;

&lt;p&gt;The number a user feels is the &lt;strong&gt;time to first token&lt;/strong&gt;. That’s the gap between letting go of the hotkey and the first word appearing. (In Fono it’s a bit more complex, but we’ll go with this.) That gap is almost entirely prefill. Decode controls how fast the answer then streams out, but prefill is what makes you sit there wondering if anything is happening.&lt;/p&gt;

&lt;p&gt;If you are not careful, a local chat assistant makes you pay prefill over and over. Every turn, the model re-reads the entire conversation so far: the system instructions, every previous question, every previous answer. All that work just to append one new sentence. Turn six pays for turns one through five all over again.&lt;/p&gt;

&lt;div id=&quot;fll-prefill-restore&quot; class=&quot;fll-widget&quot;&gt;&lt;/div&gt;

&lt;h3 id=&quot;detour-how-prefill-and-decode-stress-hardware&quot;&gt;Detour: how prefill and decode stress hardware&lt;/h3&gt;

&lt;p&gt;Let’s spend 2 minutes on this because I find it very interesting. Prefill and decode bottleneck on different parts of your computer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prefill is compute-bound.&lt;/strong&gt; All the prompt’s tokens can go through the network together, in one big parallel batch of matrix multiplications. That keeps every core and every SIMD lane (the AVX/NEON instructions that do many multiply-adds per clock) busy. More cores and wider vector instructions make prefill faster. This is why the right build of llama.cpp for your CPU matters a little bit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Decode is memory-bandwidth-bound.&lt;/strong&gt; To produce one token, the model has to read essentially all of its weights out of RAM. A 4-billion-parameter model at 4 bits is roughly 2-3 GB. Generating 100 tokens means streaming those gigabytes from memory a hundred times over. Your cores spend most of that time waiting for data, not computing. This is the dirty secret of local LLM speed. Decode is usually limited by how fast you can move the model out of RAM, not by raw math. It’s also why quantization (shrinking the weights) speeds decoding up and why fast memory matters.&lt;/p&gt;

&lt;p&gt;Of course, there are many caveats here, but let’s keep this lean :)&lt;/p&gt;

&lt;div id=&quot;fll-bandwidth&quot; class=&quot;fll-widget&quot;&gt;&lt;/div&gt;

&lt;p&gt;Two takeaways set up the rest of the post. First, since the latency you feel is dominated by prefill, and prefill cost is “how much prompt do I have to read”, the way to win is to &lt;strong&gt;read less prompt&lt;/strong&gt;. Second, the part of the prompt we re-read every turn is exactly the part that doesn’t change. We shouldn’t be reading it at all.&lt;/p&gt;

&lt;h3 id=&quot;the-trick-stop-reading-what-you-already-read&quot;&gt;The trick: stop reading what you already read&lt;/h3&gt;

&lt;p&gt;The model’s “understanding” of the prompt isn’t thrown away after prefill. It lives in a chunk of memory called the &lt;strong&gt;KV cache&lt;/strong&gt; (key/value cache, the name doesn’t matter here). Think of it as the model’s working memory of everything it has read so far.&lt;/p&gt;

&lt;p&gt;The insight that makes local models usable: &lt;strong&gt;if the start of this turn’s prompt is identical to last turn’s, the model’s working memory for that part is identical too. So don’t recompute it, reuse it.&lt;/strong&gt; Snapshot that state and next turn restore the snapshot instead of prefilling from scratch. Restoring is basically a memory copy. In Fono it takes &lt;strong&gt;15-40 milliseconds&lt;/strong&gt; regardless of size. Prefilling the same content cold can take &lt;strong&gt;seconds&lt;/strong&gt; (the right lane in the animation above). That’s the whole game.&lt;/p&gt;

&lt;p&gt;There is one ironclad rule though, and it’s where I shot myself in the foot.&lt;/p&gt;

&lt;h3 id=&quot;reuse-only-works-from-the-front&quot;&gt;Reuse only works from the front&lt;/h3&gt;

&lt;p&gt;Cache reuse only works for a prefix that is &lt;strong&gt;byte-for-byte identical from the very first token&lt;/strong&gt;. The moment something changes early in the prompt, every token after it must be recomputed. It’s like a spreadsheet. Change cell A1 and every formula below recalculates.&lt;/p&gt;

&lt;p&gt;So the order you put things in completely decides how much you get to reuse. The stuff that never changes (system prompt, tool descriptions) wants to be at the &lt;strong&gt;front&lt;/strong&gt;, forming a stable prefix you cache once and reuse forever. The stuff that changes every turn (the new thing the user just said) goes at the &lt;strong&gt;back&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I had it exactly backwards.&lt;/p&gt;

&lt;h3 id=&quot;the-dumb-bug&quot;&gt;The dumb bug&lt;/h3&gt;

&lt;p&gt;There were several dumb bugs. The model got loaded twice at some point. And other where a bit more complex. I’ll share an easy one so we can laugh together.&lt;/p&gt;

&lt;p&gt;Fono now ships with Google’s Gemma as the default local model. Gemma’s prompt format has no dedicated slot for system instructions like some models have, so when I first implemented it I glued the system prompt onto the current user turn:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[ conversation history ]
&amp;lt;start_of_turn&amp;gt;user
{the entire big system prompt + tools}
User request: {what you just said}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Read that with the prefix rule in mind. On turn one it’s fine because there is no history and the system prompt sits at the front. But on turn two, the conversation history slides in front of the system prompt. The big unchanging block is no longer at position zero. The prefix is broken. The cache misses. The model re-reads everything, every single turn.&lt;/p&gt;

&lt;p&gt;I built the entire snapshot-and-restore machine and then laid out the prompt so it could basically never fire after the first turn.&lt;/p&gt;

&lt;div id=&quot;fll-prompt-layout&quot; class=&quot;fll-widget&quot;&gt;&lt;/div&gt;

&lt;h3 id=&quot;the-fix&quot;&gt;The fix&lt;/h3&gt;

&lt;p&gt;Put the system prompt where it belongs: &lt;strong&gt;first&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Now the prompt is &lt;strong&gt;append-only&lt;/strong&gt;. Each turn only adds to the end, and everything before the new line is a byte-for-byte stable prefix. The system prompt is cached once, at startup, and reused on every turn of every conversation. Each turn, the only thing the model actually reads is the new sentence you just spoke. A couple of dozen tokens on top of a restored snapshot.&lt;/p&gt;

&lt;p&gt;I wrapped this in regression tests that walk a three-turn conversation and assert each turn’s prompt is an exact string prefix of the next turn’s. If anyone reorders the prompt and breaks the append-only property again, the tests fail loudly. I don’t trust myself to not make this mistake twice.&lt;/p&gt;

&lt;p&gt;Then I was caching garbage because the template was off but still, caching worked :)&lt;/p&gt;

&lt;h3 id=&quot;the-two-paths-and-how-they-reuse-the-cache&quot;&gt;The two paths, and how they reuse the cache&lt;/h3&gt;

&lt;p&gt;The append-only layout gives both hotkeys a stable &lt;strong&gt;base&lt;/strong&gt; at the front of the prompt. Fono prefills it once at startup, snapshots it and &lt;strong&gt;pins&lt;/strong&gt; it so it’s never evicted. For F7 (dictation) the base is your cleanup instructions plus a personal dictionary. For F8 (the assistant) it’s the system prompt plus the tool descriptions. Everything else stacks on top.&lt;/p&gt;

&lt;p&gt;Play with the buttons below to get an intuitive feel how it works.&lt;/p&gt;

&lt;div id=&quot;fll-pipeline&quot; class=&quot;fll-widget&quot;&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;F7 fans out.&lt;/strong&gt; Dictation cares which app you’re in because text for a terminal reads differently than text for a chat box. So each app gets its own snapshot and they all branch off the same pinned base. The first time you dictate into your editor, Fono restores the base, decodes the small editor context on top and saves that branch. Every dictation into the editor after that restores the editor snapshot whole and decodes nothing but your words. What you actually said is never cached. Only the reusable prefix is kept.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;F8 builds a chain.&lt;/strong&gt; The assistant is a conversation, so each turn is stacked on the previous one. Turn one restores the pinned base, decodes your first request and the reply, and saves the result as the turn-one snapshot. Turn two restores turn one and decodes only the new exchange. Nothing earlier in the conversation is ever re-read. The cost of a turn tracks what you just said, not how long you’ve been talking. Conversations expire after five idle minutes, which trims the chain back to the pinned base.&lt;/p&gt;

&lt;p&gt;Both shapes use the same two ideas. A pinned base that pays the expensive work only once, and longest-prefix restore: start from the deepest snapshot that still matches and decode only the delta.&lt;/p&gt;

&lt;h3 id=&quot;the-numbers&quot;&gt;The numbers&lt;/h3&gt;

&lt;p&gt;Same laptop, same model (Gemma 4 E2B, 4-bit quantized), same six-turn conversation. First the headline. Time to first word, turn by turn, with the cache working versus not. The “not” line is exactly what my system-in-the-tail bug produced. The gray line is ollama, which we get to in a bit.&lt;/p&gt;

&lt;div id=&quot;fll-race&quot; class=&quot;fll-widget&quot;&gt;&lt;/div&gt;

&lt;p&gt;And the same data as a table, with the checkpoint size and the restore time that replaces the growing prefill:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Turn&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;History&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Tokens&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Uncached first token&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Cached first token&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Restore&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Checkpoint&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;31&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;786 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;341 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;30 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;0.6 MB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;2&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;2&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;90&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1,917 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;641 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;39 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1.7 MB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;3&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;4&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;150&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;2,468 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;383 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;37 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;2.8 MB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;4&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;6&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;211&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;3,321 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;509 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;34 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;3.9 MB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;5&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;8&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;273&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;4,367 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;491 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;15 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;5.0 MB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;6&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;10&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;333&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;4,892 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;375 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;21 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;6.1 MB&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The uncached column climbs as the conversation grows. The cached column stays flat because each turn restores a snapshot (15-40 ms) and only reads your new sentence.&lt;/p&gt;

&lt;p&gt;To make the effect impossible to miss, I also swept the size of the cached prefix directly. Imagine an assistant with a big pile of tool definitions in its system prompt. Here is the first-token latency as that prefix grows from tiny to about 3,300 tokens, cold prefill versus cached restore:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Prefix (tool defs)&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Prefix tokens&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Cold prefill&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Cached first token&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Checkpoint&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;none&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;25&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;217 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;114 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;0.5 MB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;5 tools&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;424&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;5,143 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;115 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;7.8 MB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;10 tools&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;821&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;10,341 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;118 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;15.2 MB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;20 tools&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1,631&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;21,077 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;120 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;30.1 MB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;40 tools&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;3,251&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;44,806 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;133 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;60.0 MB&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Read the last row twice. A cold prefill of a 3,251-token system prompt takes &lt;strong&gt;45 seconds&lt;/strong&gt; on this modern CPU. The cached restore serves the first token in &lt;strong&gt;133 ms&lt;/strong&gt; and the cost is a 60 MB snapshot sitting in RAM. A little memory for a lot of saved latency.&lt;/p&gt;

&lt;p&gt;This is what makes local tool use feasible in the future. It’s already on the &lt;a href=&quot;https://github.com/bogdanr/fono/blob/main/ROADMAP.md&quot;&gt;roadmap&lt;/a&gt; :)&lt;/p&gt;

&lt;h3 id=&quot;keeping-it-bounded&quot;&gt;Keeping it bounded&lt;/h3&gt;

&lt;p&gt;Trading memory for latency is only a good trade if the memory can’t run away. The scale is smaller than it looks. The KV cache runs about &lt;strong&gt;18 KB per token&lt;/strong&gt;, so one user-and-assistant exchange adds about a megabyte. The big snapshots come from prefixes, not history. A fat tool-definition block is 60 MB on its own.&lt;/p&gt;

&lt;p&gt;Three things keep the cache in check:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Pruning.&lt;/strong&gt; While a conversation grows, each new checkpoint contains the previous one, so the old one is deleted on the spot. A short conversation sits at one live checkpoint, not one per turn.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;A rolling window.&lt;/strong&gt; Assistant memory is capped at 12 turns within a 5-minute window of activity. Once the window starts sliding, the oldest turn drops off the front, old checkpoints can’t be pruned anymore and they fall under the hard bound below. Go idle for more than 5 minutes and the history is wiped, so the next turn restores just the base. That’s the cheapest case there is.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;A hard bound.&lt;/strong&gt; Everything else (other apps’ dictation contexts, one-off window grabs, leftovers from long conversations) is capped at &lt;strong&gt;8 checkpoints and 256 MB total&lt;/strong&gt;. When a limit is crossed, the least-recently-used entry is evicted. The pinned bases are never evicted.&lt;/li&gt;
&lt;/ol&gt;

&lt;div id=&quot;fll-lru&quot; class=&quot;fll-widget&quot;&gt;&lt;/div&gt;

&lt;p&gt;One subtlety makes all this deleting safe. Each snapshot is a complete, standalone copy of the model state, not a link to the previous one. The chain is only how a snapshot gets built cheaply. Once saved, it refers to nothing else, so removing one snapshot can never corrupt another. The cost is some redundancy (the base prefix is duplicated inside every snapshot built on top of it) and that is exactly why the byte budget and the pruning exist.&lt;/p&gt;

&lt;h3 id=&quot;but-is-it-actually-faster-than-ollama&quot;&gt;But is it actually faster than ollama?&lt;/h3&gt;

&lt;p&gt;Here is where I have to be honest, because it’s easy to lie with a chart.&lt;/p&gt;

&lt;p&gt;ollama is the popular way to run local models. It’s built on the same engine (llama.cpp) that Fono uses. I imported the exact same model file into ollama and ran the exact same conversation over its local API, feeding its own replies back so its cache worked at its best.&lt;/p&gt;

&lt;p&gt;ollama is not naive. It has a server-side prefix cache too and it works. Its prefill stays roughly flat across the conversation instead of climbing. So this isn’t “clever Fono vs. clueless ollama”. It’s a tool tuned for one job vs. a general-purpose server:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Turn&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Fono cached first token&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;ollama first token&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;ollama prefill&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1 (cold)&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;341 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;2,649 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;790 ms&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;2&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;641 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1,397 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1,059 ms&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;3&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;383 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1,322 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;973 ms&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;4&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;509 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1,352 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;955 ms&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;5&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;491 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1,317 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;922 ms&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;6&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;375 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1,521 ms&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1,216 ms&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Warm, Fono is roughly &lt;strong&gt;2-4x faster&lt;/strong&gt; to the first word. On the cold first turn it’s about &lt;strong&gt;8x&lt;/strong&gt;. Both run the same weights at the same quantization, so the gap is all integration:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Fono runs the model in-process.&lt;/strong&gt; No HTTP hop to a separate server and no second copy of anything. Restoring a snapshot is a local memory operation.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Fono warms the cache at startup.&lt;/strong&gt; The system-prompt snapshot is built once when the app launches, while you’re not waiting on anything. Turn one is already as fast as turn six. ollama builds it on the first request, so its first turn is cold.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Fono lays the prompt out for maximum reuse.&lt;/strong&gt; The whole point of this post.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A fair warning. These are CPU-bound numbers on a laptop, medians of a few passes, and a little noisy. One ollama turn spiked to 5.6s and I took the median to ignore it. This is not a benchmark-suite-grade result. It shows that a tool built for one job can shave the latency that a general server leaves on the table.&lt;/p&gt;

&lt;h3 id=&quot;replicate-it-yourself&quot;&gt;Replicate it yourself&lt;/h3&gt;

&lt;p&gt;I don’t like “trust me bro” benchmarks. Everything above comes out of Fono’s own benchmark binary and a small script against ollama. Here is how to run it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The machine:&lt;/strong&gt; an 8-thread CPU, no GPU, 4 GB context. Same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gemma-4-e2b&lt;/code&gt; GGUF (4-bit) for both engines.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fono’s side.&lt;/strong&gt; Build the bench tool with the embedded llama.cpp backend and run the multi-turn conversation benchmark:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cargo build &lt;span class=&quot;nt&quot;&gt;--release&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; fono-bench &lt;span class=&quot;nt&quot;&gt;--features&lt;/span&gt; llama-local

./target/release/fono-bench assistant-conversation-cache &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--model-path&lt;/span&gt; /path/to/gemma-4-e2b.gguf &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--turn&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;turn on the kitchen light&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--turn&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;now dim it to fifty percent&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--turn&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;what&apos;s the weather tomorrow morning&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--turn&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;add milk and eggs to my shopping list&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--turn&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;set a timer for ten minutes&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--turn&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;what did I ask you to buy&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--ctx-size&lt;/span&gt; 4096 &lt;span class=&quot;nt&quot;&gt;--threads&lt;/span&gt; 8 &lt;span class=&quot;nt&quot;&gt;--batch-size&lt;/span&gt; 4096 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--iterations&lt;/span&gt; 2 &lt;span class=&quot;nt&quot;&gt;--out&lt;/span&gt; conversation-cache.json
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It replays the conversation through Fono’s actual prompt builder and for each turn reports the cold prefill, the cached restore and both first-token timings. The prefix-size sweeps are a sibling command:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;./target/release/fono-bench assistant-cache-scaling &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--model-path&lt;/span&gt; /path/to/gemma-4-e2b.gguf &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--dimension&lt;/span&gt; tools &lt;span class=&quot;nt&quot;&gt;--sizes&lt;/span&gt; 0,5,10,20,40 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--ctx-size&lt;/span&gt; 4096 &lt;span class=&quot;nt&quot;&gt;--threads&lt;/span&gt; 8 &lt;span class=&quot;nt&quot;&gt;--batch-size&lt;/span&gt; 4096 &lt;span class=&quot;nt&quot;&gt;--out&lt;/span&gt; cache-scaling-tools.json
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;(One gotcha I hit: set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--batch-size&lt;/code&gt; at least as large as your biggest prompt, or llama.cpp aborts when a single prefill overflows the logical batch.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ollama’s side.&lt;/strong&gt; Import the same GGUF and drive a growing conversation over the local API, feeding the model its own replies back so its prefix cache is maximally effective:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;FROM /path/to/gemma-4-e2b.gguf\n&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; Modelfile
ollama create fono-gemma-bench &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; Modelfile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then loop over the turns hitting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;POST /api/generate&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;raw&quot;: true&lt;/code&gt; and the same system-first, append-only prompt layout Fono emits. Record the wall-clock time to the first streamed token and the server’s reported &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;prompt_eval_duration&lt;/code&gt;. The Python script of about 40 lines lives alongside the JSON artifacts. It just builds the append-only prompt, streams the response and records timings.&lt;/p&gt;

&lt;p&gt;Point being, same model, same machine, same conversation, both numbers measured the same way. Run it and tell me if your laptop disagrees with mine.&lt;/p&gt;

&lt;p&gt;I also did GPU runs and other older CPUs but let’s keep it focused. Maybe at some point I write about how I did &lt;a href=&quot;https://fono.page/calibration/&quot;&gt;900+ benchmark runs&lt;/a&gt; to tune Fono’s first run wizard.&lt;/p&gt;

&lt;h3 id=&quot;takeaways&quot;&gt;Takeaways&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;For a local LLM, the latency you feel is prefill, and prefill is the prompt you re-read every turn.&lt;/strong&gt; Optimize that and everything feels instant.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Cache reuse only works from the front.&lt;/strong&gt; Put the unchanging stuff (system prompt, tools) first and the new stuff last. Keep the prompt append-only.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Order is an architectural decision.&lt;/strong&gt; My slowest and fastest paths generated identical text in a different order. One reused everything, one reused nothing.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Know which phase is compute-bound and which is bandwidth-bound.&lt;/strong&gt; It tells you whether more cores, a better-compiled binary or faster RAM will actually help.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Warm the cache before the user needs it, and remember it costs RAM.&lt;/strong&gt; Startup is free time, spend it. Bound the cache so it can’t eat the machine.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Test the invariant, not just the output.&lt;/strong&gt; “Each turn’s prompt is a prefix of the next” is a one-line property that would have caught my bug on day one.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The cache work is committed. Next on the list is making sure the heavy prompt-building never fights the speech-to-text engine for CPU while you’re mid-sentence. That’s a scheduling problem for another post.&lt;/p&gt;

&lt;p&gt;If you want to read the actual code, it’s all in the &lt;a href=&quot;https://github.com/bogdanr/fono&quot;&gt;Fono repository&lt;/a&gt;. GPL-3.0.&lt;/p&gt;

&lt;link rel=&quot;stylesheet&quot; href=&quot;/assets/css/fono-llm-speed.css&quot; /&gt;

&lt;script src=&quot;/assets/js/fono-llm-speed.js&quot;&gt;&lt;/script&gt;

</content>
 </entry>
 
 <entry>
   <title>Learning How To Learn</title>
   <link href="/hobby/2023/02/20/Learning-How-To-Learn.html"/>
   <updated>2023-02-20T00:00:00+00:00</updated>
   <id>/hobby/2023/02/20/Learning-How-To-Learn</id>
   <content type="html">&lt;p&gt;If you’re a little bit like me, some subjects could seem too complicated. Other times you’d find it very hard to get started with something and keep procrastinating it. Or you might find yourself very tired to learn something new. And frankly, if we overcome all these we might find it was all in vain and we forgot most of it. Let’s fix this!&lt;/p&gt;

&lt;p&gt;It’s mostly a thing of having a well-rested brain, a proper mindset and a proper technique to improve your learning a lot.&lt;/p&gt;

&lt;p&gt;As part of my &lt;em&gt;“Learning How to Learn: Powerful mental tools to help you master tough subjects”&lt;/em&gt; Coursera class I am writing this post. It’s supposed to be a gift that keeps on giving. It helps me master what I learned by repeating the concepts and it will teach someone else concepts that are supposed to be life-changing.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/brain-code.png&quot; alt=&quot;Brain code&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;the-big-picture&quot;&gt;The big picture&lt;/h2&gt;

&lt;p&gt;Many of us enjoy exploring new interests and learning new things. I think I always did, except maybe for half my life when I was in school 🙂. The school system in my country favored going for the grades and not for the education so pretty much everybody that learned, did it just before getting tested, we got our grades and then we would forget most of it. I used to think that even though in 19 years the school didn’t teach me much, at least it taught me how to learn. But it seems that is not the case either.&lt;/p&gt;

&lt;p&gt;Anyways, this is not about school systems it’s about our personal systems. I often need (for making money) or want (for health, hobbies, the sake of others, etc.) to learn more, faster, better and I find myself accomplishing way less than I think I could accomplish. It’s time to get better at learning before we can get better at other things.&lt;/p&gt;

&lt;h2 id=&quot;the-mindset&quot;&gt;The Mindset&lt;/h2&gt;

&lt;p&gt;Like many of the other things which follow, it’s essential to have the proper mindset. &lt;strong&gt;Knowledge is made by people FOR people.&lt;/strong&gt; We all start as a blank slate. We learn a HUGE amount of things by the time we grasp reading and basic arithmetic. Let’s not stop learaning, ever!&lt;/p&gt;

&lt;p&gt;If you read or listen to interesting things which you’d like to learn but you don’t apply yourself in the direction of learning them, likely that will not happen.&lt;/p&gt;

&lt;p&gt;Looking at scientific research tells us that most of us think we’re above average. Let’s use this fallacy to our advantage, believe we can learn everything and increase our chances to become above average.&lt;/p&gt;

&lt;h2 id=&quot;sleep&quot;&gt;Sleep&lt;/h2&gt;

&lt;p&gt;When you’re tired you don’t remember. As the day progresses, the brain accumulates substances that interfere with strengthening neural pathways.&lt;/p&gt;

&lt;p&gt;During sleep, the brain clears all the substances which inhibit learning.&lt;/p&gt;

&lt;p&gt;I highly recommend reading the &lt;a href=&quot;https://www.goodreads.com/book/show/40781394-why-we-sleep&quot;&gt;Why We Sleep&lt;/a&gt; book (ISBN 9781501144318). It presents many other advantages to having proper sleep which will also be good for your learning.&lt;/p&gt;

&lt;h2 id=&quot;thinking-modes&quot;&gt;Thinking modes&lt;/h2&gt;

&lt;p&gt;Our brain has two modes of thinking:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Focused mode thinking&lt;/li&gt;
  &lt;li&gt;Diffused mode thinking&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In focused mode thinking we can point our mind to e narrow subject, just like a searchlight. It helps us understand that specific thing so we can then store it in memory, thus forming a chunk of information. Focused mode thinking uses a lot of mental energy and it’s not sustainable for prolonged periods. Also, when we’re in focused mode our vision is very narrow and often we can’t clearly see the bigger picture.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/Searchlight.jpg&quot; alt=&quot;Difused mode thinking&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Diffused mode thinking is a more relaxed way of thinking when we just let our minds wander. We let the thoughts pop into our minds as they please and it’s often a very good source of general problem-solving and creativity. We can stimulate diffuse mode thinking by walking or doing other relaxing activities that don’t grab your focus. During the diffused mode thinking, the chunks we formed in focus mode interact in a relaxed fashion.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/Think-Outside-the-Box.png&quot; alt=&quot;Focused mode thinking&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Both modes are very important. Thinking works best by alternating between these two.&lt;/p&gt;

&lt;h2 id=&quot;memory&quot;&gt;Memory&lt;/h2&gt;

&lt;p&gt;Although our memory is very complex, for the sake of grasping the main ideas as quickly as possible we are going to touch a little on the main two branches, short-term memory and long-term memory.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/human-memory.png&quot; alt=&quot;Brain&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Our short-term memory, often described as working-memory, is handled by our prefrontal cortex and it &lt;strong&gt;can only store 4±1 items for just 15-30 seconds&lt;/strong&gt;, according to Cowan (2001) and Atkinson and Shiffrin (1968). We’re using this memory pretty much for any type of thinking and it’s important to understand its limitations.&lt;/p&gt;

&lt;p&gt;This memory is small, easily distracted, and very short-lived. If I am focused on my work and notifications fire on the computer and the phone, they bump items out of my short-term memory. If I actually check out those notifications, the short-term memory gets wiped out and I need to recreate it. This process requires energy and our brain gets tired faster in the process.&lt;/p&gt;

&lt;p&gt;When we’re working with chunks of information (pieces that we already have in the long-term memory), they use less space in our working memory. To solve complex problems we first need to develop the necessary chunks.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/Brain.png&quot; alt=&quot;Brain&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Long-term memory is VAST. It is comparable to a warehouse where pieces of information stay until they’re needed. Like a warehouse, different areas seem to be used for storing different types of information. Walking, biking and writing are part of our unconscious memory and we call this implicit memory.&lt;/p&gt;

&lt;p&gt;Knowledge about factual information, like how you use some software on your computer, is called semantic memory and it’s part of our explicit memory. Semantic memory is subject to fading and we can protect from that through deliberate recall.&lt;/p&gt;

&lt;p&gt;Things get into the long-term memory when after the information is manipulated in the short-term memory and then it’s encoded by the hippocampus. Repeating the information activates and strengthens the neural pathways related to that piece of information. If the hippocampus gets damaged you can still retrieve memories but you can’t form new ones. The protagonist of the movie &lt;a href=&quot;https://www.imdb.com/title/tt0209144/&quot;&gt;Memento&lt;/a&gt; had this problem.&lt;/p&gt;

&lt;h3 id=&quot;chunking&quot;&gt;Chunking&lt;/h3&gt;

&lt;p&gt;As we learn a concept, it becomes a chunk of information and it gets stored in the long-term memory. When we grasp it clearly, this chunk takes only one slot in our working memory.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/Chunking-Technique.png&quot; alt=&quot;Chunking&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Our diffused mode thinking interacts with different chunks, sometimes even from different areas of knowledge, to come to a solution for a complex problem.&lt;/p&gt;

&lt;h3 id=&quot;spaced-repetition&quot;&gt;Spaced repetition&lt;/h3&gt;

&lt;p&gt;We mentioned before that repeating a piece of information makes it stick. Instead of doing all the work of memorizing in one big session, it’s way more effective to split it across multiple days into much shorter sessions. If you learn the subject at once you’re way more likely to forget it and have a bad day.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/Spaced-Repetition.png&quot; alt=&quot;Chunking&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This technique of learning was studied multiple times since 1932 and has been proven to increase the rate of learning.&lt;/p&gt;

&lt;p&gt;Spaced repetition allows us to be more chill about learning and learn better.&lt;/p&gt;

&lt;p&gt;For example, Duolingo, the popular language app employs spaced repetition as the main teaching mechanism. Headway tries to apply this to books. A general-purpose tool for doing spaced repetition is &lt;a href=&quot;https://apps.ankiweb.net/&quot;&gt;Anki&lt;/a&gt;. Let me know if you find something better.&lt;/p&gt;

&lt;h3 id=&quot;procrastination&quot;&gt;Procrastination&lt;/h3&gt;

&lt;p&gt;When we think about starting to work on a complex task our brain actually feels pain. Not like skin pain, but brain pain. And it wants to protect itself by changing our attention to something way easier, like surfing on the Internet or talking to other people.&lt;/p&gt;

&lt;p&gt;If we get started with our task, the pain goes away very quickly and we can then focus on our task. A notification would break that focus and we’d have to go through that initial pain again. And another problem is that going through this pain uses the limited willpower we have during a day.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/Procrastination.png&quot; alt=&quot;Procrastination&quot; /&gt;&lt;/p&gt;

&lt;p&gt;There are a few key actions that we can do here:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Start early with the task that would require the most willpower&lt;/li&gt;
  &lt;li&gt;Minimize notifications so we don’t waste energy on overcoming the pain over and over again&lt;/li&gt;
  &lt;li&gt;Take deliberate breaks to rest and do diffuse mode thinking&lt;/li&gt;
  &lt;li&gt;Treat yourself so that you train your brain that at the end of a work session something good is coming&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The most well-known technique for fighting procrastination is the Pomodoro method. Its basic principle is that you work for 25 minutes and then take a break for 5 minutes. After two hours you’ve done 4 pomodoros and you can take a 30-minute break.&lt;/p&gt;

&lt;p&gt;The Pomodoro method doesn’t really work for me. I need longer than 25 minutes sessions so I will invent the Rădulescu method. 50 minutes of work and 10-20 minutes of break. It’s not yet clear how many of these sessions I would do in a day but I’ll try different things.&lt;/p&gt;

&lt;h3 id=&quot;illusion-of-competence&quot;&gt;Illusion of competence&lt;/h3&gt;

&lt;p&gt;If you know how to drive a car and you look at F1 races, you might think you could drive an F1 car. This is a well-known cognitive bias called the Dunning-Kruger effect.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/Dunning-Graph.png&quot; alt=&quot;Illusion of Competence&quot; /&gt;&lt;/p&gt;

&lt;p&gt;When I started to write this blog post about learning how to learn I thought it was going to be quick and easy. I got 100% on my test so to me that looked like I mastered the subject matter. In reality, I am 5 hours into this and still learning.&lt;/p&gt;

&lt;p&gt;You can only know for sure you are competent in a subject when you do it yourself. Test yourself!&lt;/p&gt;

&lt;h3 id=&quot;what-next&quot;&gt;What next?!&lt;/h3&gt;

&lt;p&gt;If you feel it’s worth keeping anything out of this I will give you an assignment. Drop me a message with &lt;strong&gt;3 key points&lt;/strong&gt; which you think will improve your learning the most. This exercise WILL strengthen neural pathways especially if you go over those key points on different days during a week.&lt;/p&gt;

&lt;p&gt;Looking forward to your message!&lt;/p&gt;

&lt;object data=&quot;https://bogdan.nimblex.net/assets/doc/Coursera-J3HH3KZ7B974.pdf&quot; width=&quot;800&quot; height=&quot;650&quot; type=&quot;application/pdf&quot;&gt;&lt;/object&gt;
</content>
 </entry>
 
 <entry>
   <title>Taking my first photo of the Milky Way</title>
   <link href="/hobby/2019/08/03/My-First-MilkyWay-photo.html"/>
   <updated>2019-08-03T00:00:00+00:00</updated>
   <id>/hobby/2019/08/03/My-First-MilkyWay-photo</id>
   <content type="html">&lt;p&gt;While searching for a hobby for my wife I got interested in photography. It seems that I am especially drawn towards low light photography which I understand is what “normal” photographers don’t usually do. I played a little with my phone in low light situations and even though it’s amazing where things are in 2019, it’s still not good enough for what I am looking for.&lt;/p&gt;

&lt;h2 id=&quot;the-gear&quot;&gt;The gear&lt;/h2&gt;

&lt;p&gt;Of course, part of the fun is getting the gear so after doing a little bit of research I decided to get the Sony A6000 because “they” say it’s a very capable &lt;strong&gt;compact&lt;/strong&gt; mirrorless camera. I was also considering RX100 and A7 because the first one is way more compact and the second one more capable but bulkier, I feel this one I chose is a good middle ground.&lt;/p&gt;

&lt;h3 id=&quot;about-lenses&quot;&gt;About lenses&lt;/h3&gt;

&lt;p&gt;My understanding right now is that the glass is the most important thing if you have a decent camera. Also, there is no point in having a very good camera if you don’t have a decent lens because it will probably not make a difference.&lt;/p&gt;

&lt;p&gt;There are 4 main properties to consider for lenses and some other less important things:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Focal length&lt;/li&gt;
  &lt;li&gt;Aperture&lt;/li&gt;
  &lt;li&gt;Manual or not&lt;/li&gt;
  &lt;li&gt;Image quality&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;1-focal-length&quot;&gt;1. Focal length&lt;/h4&gt;

&lt;p&gt;Generally speaking, is a measure of that fits into the frame. A small focal length makes wide pictures which fit a lot into the frame and a high focal length number “zooms” a lot bringing the subject closer. The image below should make it the basic concept clear.
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/focal-length-examples.jpg&quot; alt=&quot;Focal Length&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The focal length also changes how compressed things appear in the background.
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/focal-length-portrait.gif&quot; alt=&quot;Focal Length&quot; /&gt;
In this example, the zoom is done with the legs so the subject is kept in the frame. As you can see, the background changes drastically.&lt;/p&gt;

&lt;p&gt;The first lens I got is a versatile 18-200mm which means that I can take both wide and significantly zoomed-in photos.&lt;/p&gt;

&lt;h4 id=&quot;2-aperture&quot;&gt;2. Aperture&lt;/h4&gt;

&lt;p&gt;The aperture is the opening through which the light enters the camera. Lenses have a variable aperture but we care about the smaller number which represents how much the aperture opens thus allowing more light in.
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/aperture-explained.jpg&quot; alt=&quot;Aperture&quot; /&gt;&lt;/p&gt;

&lt;p&gt;A lens with a smaller aperture is called a fast lens because more light comes in thus we can expose for a shorter time and catch faster-moving subjects.&lt;/p&gt;

&lt;p&gt;Changing the aperture also influences what is kept in focus.
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/aperture.gif&quot; alt=&quot;Aperture&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The second lens I got for photographing the stars is an f/2.0, 12mm which should allow for capturing lots of lite and a decent portion of the sky.&lt;/p&gt;

&lt;h4 id=&quot;3-manual-or-not&quot;&gt;3. Manual or not&lt;/h4&gt;

&lt;p&gt;Manual lenses are just what the name says. They don’t have motors or electronics and can easily be adapted to different camera systems. For setting the focus and aperture they have some ring which you turn. The zoom lenses also have a ring for that.
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/lens-teardown.jpg&quot; alt=&quot;Lens teardown&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Normally I would prefer a lens with autofocus but for some applications such as night photography, it doesn’t matter because you set it once and live it like that.&lt;/p&gt;

&lt;p&gt;The 18-55mm kit lens of my camera has a lot of “auto” in it. Autofocus, auto-aperture, optical stabilization and even motors for zoom. Of course, all these auto things can be set to manual and configured with buttons from the camera.&lt;/p&gt;

&lt;p&gt;I wouldn’t say one is better than the other, it just depends on what you do with it. I like that my 12mm, f/2 lens is manual because to me it means that most of the cost comes from having better glass. And I also like that my “walk-around” lens has a lof of auto because that optical stabilization is a very nice feature when taking pictures zoomed in and handheld.&lt;/p&gt;

&lt;h4 id=&quot;4-image-quality&quot;&gt;4. Image quality&lt;/h4&gt;

&lt;p&gt;Glass is not perfect and physics not on our side when light is bent in complex ways. The science of producing a good lens deals with issues such as distortion, chromatic aberration, vignetting, lens flare and others. To fight these issues lenses use multiple glass elements combined into groups. The issue with this is that the more elements are used the more light is lost due to reflections. The glass can have antireflection coating but I guess you can see why lenses can get expensive.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/chromatic-aberration-star-example.jpg&quot; alt=&quot;Chromatic Aberations&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Distortion_(optics)&quot;&gt;Distortions&lt;/a&gt; are more of an issue with wide-angle lens and &lt;a href=&quot;https://en.wikipedia.org/wiki/Chromatic_aberration&quot;&gt;chromatic aberrations&lt;/a&gt; with faster lens used wide open. Combine that with a high contrast image of stars against the dark void of space and you probably have the least favorable scenario.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://www.rokinon.com/lenses/digital-photo-lenses/12mm-f20&quot;&gt;12mm, f/2&lt;/a&gt; which I got for night photography is supposed to be pretty good quality.&lt;/p&gt;

&lt;h3 id=&quot;about-the-camera-body&quot;&gt;About the camera body&lt;/h3&gt;

&lt;p&gt;I wanted to get a camera which is affordable, compact and way better than my phone.&lt;/p&gt;

&lt;p&gt;It’s a lot to consider when you get the first camera and don’t know what you get into:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Body type: DSLR, mirrorless, point-and-shoot, stick to the phone :)&lt;/li&gt;
  &lt;li&gt;Sensor size: 1 inch, APS-C, Full Frame&lt;/li&gt;
  &lt;li&gt;Brands: Canon, Nikon, Sony, Fuji, etc&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;1-body-type&quot;&gt;1. Body type&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/MirrorlessVsDSLR.jpg&quot; alt=&quot;mirrorless vs DSLR&quot; /&gt;
The main thing I considered here it’s that it’s supposed to be compact and capable. 
DSLR is too bulky for me and I think it’s just older tech without any real advantage.
The point and shoot cameras “feel” too limiting since you can’t change lenses on them, even though RX100 really seems way better than a phone.&lt;/p&gt;

&lt;h4 id=&quot;2-sensor-size&quot;&gt;2. Sensor size&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/full-frame-aps-c-1inch.jpg&quot; alt=&quot;sensor size&quot; /&gt;&lt;/p&gt;

&lt;p&gt;For the same number of megapixels, a larger sensor has a larger pixel and thus can collect more photons of light. Then the signal to noise ratio is higher and thus the image can be better. This is especially important in low light photography when we need to amplify the signal a lot (set a high ISO) to see the very little available light.&lt;/p&gt;

&lt;p&gt;The most recent phones which produce usable images in low light with a very small sensor do a lot of post-processing and what you get is not what the sensor sees. As a fun fact, a sensor in a phone is more than 10x smaller than a sensor in a cheap mirrorless camera.&lt;/p&gt;

&lt;p&gt;The most common sensor sizes are full-frame, APS-C, 4/3 and 1 inch.
Full-frame cameras are too large for my taste and the lenses are more expensive and they also need to be bigger. I don’t see myself caring these with me. The next best thing is APS-C which looks like something that I’d drag with me on vacations or to the park.&lt;/p&gt;

&lt;h4 id=&quot;3-brands&quot;&gt;3. Brands&lt;/h4&gt;

&lt;p&gt;There is a lot of variation here and once you choose a brand you kinda get locked in the ecosystem. Manufacturers usually have their own mount for lenses and while adapters exist it’s not ideal especially for lenses with electronics#### 3. Brands&lt;/p&gt;

&lt;p&gt;There is a lot of variation here and once you choose a brand you kinda get locked in the ecosystem. Manufacturers usually have their own mount for lenses and while adapters exist it’s not ideal especially for lenses with electronics.&lt;/p&gt;

&lt;p&gt;Sony seems to dominate the mirrorless game so far so I choose the A6000. It looks like their lenses are more expensive and less available than the Nikon lenses but so far I don’t regret my choice. Having almost no experience with other cameras I have nothing to complain :)&lt;/p&gt;

&lt;h3 id=&quot;preparing-to-photograph-the-stars&quot;&gt;Preparing to photograph the stars&lt;/h3&gt;

&lt;p&gt;In this case, I need to find a very dark place on a very dark day with clear skies.&lt;/p&gt;

&lt;p&gt;The very dark day was 1st August 2019 when it was a new moon which means the moon was completely in the shadow. We have one of these every month. I was quite lucky the first one had clear skies and that I didn’t have something else to do.&lt;/p&gt;

&lt;p&gt;The very dark place can be found looking at a light pollution map like &lt;a href=&quot;https://www.lightpollutionmap.info&quot;&gt;lightpollutionmap.info&lt;/a&gt;. 
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/lightmap.png&quot; alt=&quot;Light polution map&quot; /&gt;
I live in Bucharest so I can find some very dark places ~100km away.&lt;/p&gt;

&lt;p&gt;I’ve ended up ~70km away because I thought it was dark enough and very convenient. The next day I found out that I was in a class 4 zone on the &lt;a href=&quot;https://www.handprint.com/ASTRO/bortle.html&quot;&gt;Bortle scale&lt;/a&gt;. If I’ve driven for an hour more I certainly could have reached a darker place (class 3).&lt;/p&gt;

&lt;p&gt;Once you have the day, the place and the weather, all you have to do is put the camera on a tripod and make these settings on the camera:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;exposure: for my 12mm lens, the exposure is supposed to be 27 seconds to avoid star trails. I’ve set it to 30” because the other option on my camera was 20” and that was too little.&lt;/li&gt;
  &lt;li&gt;aperture: opened it all the way to f/2&lt;/li&gt;
  &lt;li&gt;ISO: I experimented between 1600-3200. I feel like 3200 was a bit too much but the picture I’m going to share was shot with ISO 3200 and then the exposure was taken down in lightroom because I liked it more from the bunch.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;the-result&quot;&gt;The result&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/MilkyWay1.jpg&quot; alt=&quot;Milky Way first attempt&quot; /&gt;
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/MilkyWay1-bw.jpg&quot; alt=&quot;Milky Way first attempt BW&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;what-next&quot;&gt;What next?!&lt;/h3&gt;

&lt;p&gt;I realize it can be better in various ways, but to be honest I’m satisfied with this first attempt.
If there is going to be the next time, I want to go to a place with even less light pollution, try to make a timelapse and learn how to actually edit these. Also, I could experiment with stacking and if I find something interesting to put in the frame also experiment with light painting.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>How to give access on AWS to a consultant</title>
   <link href="/cloud/2019/04/03/Give-access-to-AWS.html"/>
   <updated>2019-04-03T00:00:00+00:00</updated>
   <id>/cloud/2019/04/03/Give-access-to-AWS</id>
   <content type="html">&lt;p&gt;I am a DevOps consultant so I have access to a bunch of AWS accounts, in addition to my own. If I was to use individual credentials for each account, it would be very inconvenient especially since I have to switch between accounts multiple times a day. For a while now, AWS has a nice feature which allows me to access multiple accounts from my own AWS account. This feature is called &lt;strong&gt;Roles&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The official documentation for this is &lt;a href=&quot;https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-console.html&quot;&gt;easily available&lt;/a&gt; but maybe not so easy to understand by everybody.&lt;/p&gt;

&lt;p&gt;This guide is intended to be the most straightforward way of giving access to a person who uses more than one AWS account.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/IAMRoles.png&quot; alt=&quot;IAM Roles switching&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;setting-up-a-role-for-access-from-another-account&quot;&gt;Setting up a role for access from another account&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;Go to &lt;strong&gt;IAM&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Roles&lt;/strong&gt; and click &lt;a href=&quot;https://console.aws.amazon.com/iam/home#/roles$new&quot;&gt;Create role&lt;/a&gt;. Ask for the account ID.
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/IAMRolesNew1.png&quot; alt=&quot;IAM Roles New1&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;Go through each step one by one and select the appropriate permissions.
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/IAMRolesNew2.png&quot; alt=&quot;IAM Roles New2&quot; /&gt;
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/IAMRolesNew3.png&quot; alt=&quot;IAM Roles New3&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;Cases matter. I use Bogdan every time so it’s easy to remember.
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/IAMRolesNew4.png&quot; alt=&quot;IAM Roles New4&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;Click &lt;strong&gt;Create role&lt;/strong&gt; and if you’re only in charge of giving access your job is done.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;using-this-new-role-in-your-main-account&quot;&gt;Using this new role in your main account&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;Click your account name from the top right corner and find the Switch Role button.
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/IAMRolesSwitch1.png&quot; alt=&quot;AWS Switch Role&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;Fill in all the info.
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/IAMRolesSwitch2.png&quot; alt=&quot;AWS Switch Role data&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;Enjoy this faster way of switching AWS accounts.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There is a limitation though to a maximum of 5 accounts but if you just learned about this I am sure you can live with this limitation :)&lt;/p&gt;

&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;This is a nice time-saving feature which facilitates using multiple AWS accounts. AWS was somewhat late in the game with this feature. Others from my toolbox that support something similar are CloudFlare, GoDaddy and obviously Google.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Internationalized domain names ...in Linux</title>
   <link href="/linux/2018/08/01/IDNs-in-linux.html"/>
   <updated>2018-08-01T00:00:00+00:00</updated>
   <id>/linux/2018/08/01/IDNs-in-linux</id>
   <content type="html">&lt;p&gt;The Internet was made for Latin script, more specifically a-z, 0-9 and a hyphen. Of course, I’m talking about Internet addresses, which is exactly how you reach content online. The problem is that around 2 billion people actually use Chinese, Arabic, Devanagari, Cyrillic and other writing systems. Even the French, Germans and Romanians have non-latin characters so let’s see how those are handled online.&lt;/p&gt;

&lt;p&gt;I got the domain &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ă.cc&lt;/code&gt;. How can I use it?&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/IDNs.jpg&quot; alt=&quot;IDNs map&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;some-background-info&quot;&gt;Some background info&lt;/h3&gt;

&lt;p&gt;The DNS, which is the system that helps us get around online using names instead of IP addresses is restricted to only ASCII characters. It makes sense to me because:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;The Americans who invented DNS can’t really be blamed that they didn’t think of characters they didn’t understand.&lt;/li&gt;
  &lt;li&gt;Coordinating the update of many servers on the Internet to support some major new feature is not reasonable.&lt;/li&gt;
  &lt;li&gt;Adding UTF-8 could be a huge liability. It has some strange characters such as &lt;strong&gt;blank&lt;/strong&gt; and &lt;strong&gt;go back one character&lt;/strong&gt;. This would open interesting possibilities.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nevertheless, in 1996 a guy from Zurich felt that we need domains with all types of characters so he wrote &lt;a href=&quot;https://tools.ietf.org/html/draft-duerst-dns-i18n-00&quot;&gt;a draft&lt;/a&gt;. People implemented, debated and more than a decade later, &lt;a href=&quot;https://www.icann.org/news/announcement-2009-10-30-en&quot;&gt;in 2009 ICANN brought the languages of the world to the global Internet&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Internationalized domain names (IDNs for short) are domain names which use non-ASCII characters and could be helpful to more than 30% of the world population.&lt;/p&gt;

&lt;p&gt;But all this time DNS didn’t change, so how does this work?!&lt;/p&gt;

&lt;p&gt;At some point, &lt;a href=&quot;https://tools.ietf.org/html/rfc3492&quot;&gt;some guy proposed a standard&lt;/a&gt; for converting any character (Unicode) into ASCII. This is called Punycode. For my domain, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ă.cc&lt;/code&gt;, Punycode looks like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xn--0da.cc&lt;/code&gt;. The character &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ă&lt;/code&gt; is actually &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0da&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xn--&lt;/code&gt; tells applications this is Punycode.&lt;/p&gt;

&lt;p&gt;So, IDNs are implemented at the application level. Internet Explorer started to support this late 2006 and others a little bit earlier but it seems that 12 years later, support is poor in pretty much any other basic tool.&lt;/p&gt;

&lt;h3 id=&quot;the-linux-situation&quot;&gt;The Linux situation&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;SSH, traceroute and many others don’t support IDNs.&lt;/li&gt;
  &lt;li&gt;The browsers, nslookup and dig are OK.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
  &lt;li&gt;The thing that handles resolving domain names in Linux is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;glibc&lt;/code&gt;, which has some resolver code copied mostly from BIND. BIND is that DNS server which we talked about in the beginning, that only supports ASCII.&lt;/li&gt;
  &lt;li&gt;Pretty much all programs link against &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;glibc&lt;/code&gt; and when they need to resolve some address, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;glibc&lt;/code&gt; handles it for them.&lt;/li&gt;
  &lt;li&gt;There is a library in Linux, called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libidn&lt;/code&gt;, which handles the conversion to Punycode.&lt;/li&gt;
  &lt;li&gt;
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;nimblex:~# ldd /usr/bin/nslookup 
 linux-vdso.so.1 (0x00007ffc3dde8000)
 libedit.so.0 =&amp;gt; /usr/lib64/libedit.so.0 (0x00007fed5f979000)
 libdns.so.1100 =&amp;gt; /usr/lib64/libdns.so.1100 (0x00007fed5f551000)
 liblwres.so.160 =&amp;gt; /usr/lib64/liblwres.so.160 (0x00007fed5f33e000)
 libbind9.so.160 =&amp;gt; /usr/lib64/libbind9.so.160 (0x00007fed5f12d000)
 libisccfg.so.160 =&amp;gt; /usr/lib64/libisccfg.so.160 (0x00007fed5ef01000)
 libisc.so.169 =&amp;gt; /usr/lib64/libisc.so.169 (0x00007fed5ec89000)
 libcrypto.so.1.1 =&amp;gt; /lib64/libcrypto.so.1.1 (0x00007fed5e802000)
 libcap.so.2 =&amp;gt; /lib64/libcap.so.2 (0x00007fed5e5fd000)
 libjson-c.so.4 =&amp;gt; /usr/lib64/libjson-c.so.4 (0x00007fed5e3ee000)
 libpthread.so.0 =&amp;gt; /lib64/libpthread.so.0 (0x00007fed5e1cf000)
 libxml2.so.2 =&amp;gt; /usr/lib64/libxml2.so.2 (0x00007fed5de6a000)
 libz.so.1 =&amp;gt; /lib64/libz.so.1 (0x00007fed5dc53000)
 liblzma.so.5 =&amp;gt; /lib64/liblzma.so.5 (0x00007fed5da2d000)
 libm.so.6 =&amp;gt; /lib64/libm.so.6 (0x00007fed5d692000)
 libdl.so.2 =&amp;gt; /lib64/libdl.so.2 (0x00007fed5d48e000)
 libidn.so.12 =&amp;gt; /usr/lib64/libidn.so.12 (0x00007fed5d25a000)
 libc.so.6 =&amp;gt; /lib64/libc.so.6 (0x00007fed5ce70000)
 libncurses.so.6 =&amp;gt; /lib64/libncurses.so.6 (0x00007fed5cc46000)
 libtinfo.so.6 =&amp;gt; /lib64/libtinfo.so.6 (0x00007fed5ca1a000)
 /lib64/ld-linux-x86-64.so.2 (0x00007fed5fbb1000)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;nslookup links against libidn and that’s why it can resolve my domain; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ă.cc&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now a few things come to mind:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;link &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;glibc&lt;/code&gt; against &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libidn&lt;/code&gt; to support resolving internationalized domains names. Well, this is stupid because &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;glibc&lt;/code&gt; is primordial. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libidn&lt;/code&gt; links to it, not the other way around.
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;nimblex:~# ldd /usr/lib64/libidn.so.12
  linux-vdso.so.1 (0x00007ffe1cbdc000)
  libc.so.6 =&amp;gt; /lib64/libc.so.6 (0x00007fc7f9785000)
  /lib64/ld-linux-x86-64.so.2 (0x00007fc7f9da3000)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;merge &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;glibc&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libidn&lt;/code&gt;. It seems this &lt;a href=&quot;https://ftp.gnu.org/gnu/libc/glibc-libidn-2.10.1.tar.bz2&quot;&gt;was done&lt;/a&gt; before ICAN made their grand announcement, almost a decade ago, but then abandoned.&lt;/li&gt;
  &lt;li&gt;link tools like ping, ssh and others against &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libidn&lt;/code&gt;.
    &lt;ul&gt;
      &lt;li&gt;it looks like for ping, libidn was &lt;a href=&quot;https://github.com/iputils/iputils/commit/f3a461603ef4fb7512ade3bdb73fe1824e294547&quot;&gt;encouraged since 2015&lt;/a&gt; but many distros don’t support it yet. Still, I’m sure ping will support IDNs in most distros soon.&lt;/li&gt;
      &lt;li&gt;for ssh the territory is virgin.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;In 2018 we have AI which recognizes my face better than my family but most tools don’t work with domains such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;рнидс.срб&lt;/code&gt;. It seems seriously limiting and I don’t like that. I guess I will start bothering some people about this.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Pedal car electric conversion - preparation</title>
   <link href="/diy/2018/06/26/electric-car-conversion-preparation.html"/>
   <updated>2018-06-26T00:00:00+00:00</updated>
   <id>/diy/2018/06/26/electric-car-conversion-preparation</id>
   <content type="html">&lt;p&gt;I did an impulse buy and got a &lt;a href=&quot;https://www.baghera.co.uk/pedal-cars/13-legend-red.html&quot;&gt;Baghera Legend Red&lt;/a&gt; for my son and I decided to convert it from clean and boring pedal power to dirty and fun electric power. In this first part, I will do calculations and planning so I don’t order too many useless parts.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/pedal-car/pedal-car1.jpg&quot; alt=&quot;Baghera Legend&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;the-motor&quot;&gt;The motor&lt;/h3&gt;

&lt;p&gt;Of course, it all starts with the motor. It needs to be:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;cheap (it’s a pedal car conversion)&lt;/li&gt;
  &lt;li&gt;fairly small and light&lt;/li&gt;
  &lt;li&gt;powerful enough to move 20Kg&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At ~24V there is a good selection of motors which would do it for this application. Electric scooter motors start at 250W so I guess I want something that handles 30-150W.&lt;/p&gt;

&lt;p&gt;With motors I don’t think it’s proper to rate them only by voltage, current and power because you’re putting electricity through a wire/coil which creates a magnetic field that makes the motor turn. If the motor draws more current then it heats up and the wire insulation could be damaged. Usually, motors draw more current when they are loaded so I consider the rating loosely and I’d keep an eye on the temperature.&lt;/p&gt;

&lt;p&gt;I have no problem getting a motor rated for 30W nominal and run it at 100W for a minute or so. It would only shorten the life of the motor slightly and it would provide the bursts of acceleration which are all the fun.&lt;/p&gt;

&lt;p&gt;I got a good deal on &lt;a href=&quot;https://www.dunkermotoren.com/en/products/brushed-dc-motors/detail/8844201221/&quot;&gt;this motor&lt;/a&gt; which is going to work just fine at 50-100W.
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/pedal-car/motor-diagram.png&quot; alt=&quot;GR-63x25&quot; /&gt;
This one has a nice diagram showing the specs. Most of the cheaper ones don’t.&lt;/p&gt;

&lt;h3 id=&quot;the-battery-pack&quot;&gt;The battery pack&lt;/h3&gt;

&lt;p&gt;Once we have a general idea about our motor size we can think about the battery pack. We don’t really have real-life numbers with it but again, we make some assumptions.&lt;/p&gt;

&lt;p&gt;The battery pack needs to satisfy 3 things:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;voltage ~24V. This will allow us to reach higher speeds but also to extract power from the motor.&lt;/li&gt;
  &lt;li&gt;current handling &amp;gt;5A. To run our motor at 100W. We need this to accelerate faster or to go uphill.&lt;/li&gt;
  &lt;li&gt;capacity &amp;gt;50Wh. To get a decent play time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/pedal-car/batteries.jpg&quot; alt=&quot;Batteries&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It could be as easy as &lt;strong&gt;2x12V 7Ah UPS batteries&lt;/strong&gt;. Both are less than 30$ new around here. The main disadvantage is that they weigh 4KG. Other than that these would be good because they have excellent current handling capability. One disadvantage though is that SLA batteries have this capacity if they are discharged at a very low rate, in 10-20 hours. If we &lt;a href=&quot;http://www.power-sonic.com/images/powersonic/sla_batteries/ps_psg_series/12volt/PS1270.pdf&quot;&gt;discharge the SLA battery&lt;/a&gt; in 1 hour it’s capacity would be closer to 2/3 of what it says on the tin. Smaller capacity UPS batteries cost a little more because they’re not that common and weight just a little less.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Li-Ion has a better energy density&lt;/strong&gt; (smaller &amp;amp; lighter) but the pack would be more expensive. One cell is 3.7V nominal so 24/3.7 =&amp;gt; 6 batteries and a half. I’d go for 7 batteries in series because I want to have enough voltage even when the cells are discharged. When the batteries are fully charged the voltage is closer to 30V but that’s not bad for us. One cell is usually 2.2-3Ah and it’s not recommended to pull more than 4A of one of those cells. There are some high discharge cells on the market but those are more expensive. We can improve both current handling and capacity by adding more batteries in parallel. It looks like &lt;strong&gt;the pack that we need is 7S2P&lt;/strong&gt; (7 series 2 parallel). This would provide a similar runtime for 1/4 of the weight and 2x the cost.&lt;/p&gt;

&lt;h3 id=&quot;the-speed-controller&quot;&gt;The speed controller&lt;/h3&gt;

&lt;p&gt;To control the speed of the motor we need to control the voltage that gets to it. Usually, this is &lt;a href=&quot;https://www.electronics-tutorials.ws/blog/pulse-width-modulation.html&quot;&gt;done with PWM&lt;/a&gt; (pulse width modulation) on a MOSFET. Something similar was done for &lt;a href=&quot;https://bogdan.nimblex.net/diy/2017/10/12/flashlight-with-software.html&quot;&gt;a flashlight&lt;/a&gt; in the past.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/PWM.gif&quot; alt=&quot;PWM&quot; /&gt;&lt;/p&gt;

&lt;p&gt;To control direction and braking, we need 4 of those MOSFETs in an H-bridge configuration. Also, those MOSFETs are coupled with a flyback diode to dissipate the inductive energy that is characteristic to motors.
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/pedal-car/h-bridge.png&quot; alt=&quot;H-bridge&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The cheaper speed controllers are just 10$ so I’m going to buy one because this project is not about the speed controller. Knowing how it works should help in case it breaks.&lt;/p&gt;

&lt;h3 id=&quot;the-drivetrain&quot;&gt;The drivetrain&lt;/h3&gt;

&lt;p&gt;To transfer power from the motor to the wheels, I think there are 3 practical options:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;gears (hard to mount)&lt;/li&gt;
  &lt;li&gt;chain drive (more efficient)&lt;/li&gt;
  &lt;li&gt;belt drive (less noisy and doesn’t require lubrication)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I am choosing belt drive because I care about noise and not having to grease it.&lt;/p&gt;

&lt;p&gt;There is a large variety for belt drive and I am going for timing pulleys of the HTD3M variety because they are fairly common, with decent performance and not expensive.
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/pedal-car/pulleys-performance.png&quot; alt=&quot;Timing pulleys&quot; /&gt;
When transferring power from the motor we need to reduce the RPM and increase the torque. The driving pulley is the smaller one and the math is like this:
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/pedal-car/pulley.gif&quot; alt=&quot;Timing pulleys&quot; /&gt;
If the driving pulley has 15T (T = teeth) and the driven one has 120T then RPM is decreased 8 times. Our motor is rated for 3300 RPM so, at the axle we’d have 3300/8 ~ 412RPM. Because the diameter of our wheels is 10” then the theoretical top speed is 20KM/h. That’s very nasty for a pedal car which will be driven by a toddler.&lt;/p&gt;

&lt;p&gt;After doing &lt;a href=&quot;http://www.sdp-si.com/PDFS/Technical-Section-Timing.pdf&quot;&gt;a little bit more reading&lt;/a&gt;, it seems that because of the higher RPM I can’t really use a 15T pulley, I have to use a 20T one. This means lower torque and high speed up to 26KM/h. I see these options:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;limit top speed electronically (torque stays the same but it’s simpler for me)&lt;/li&gt;
  &lt;li&gt;add another set of pulleys (gain more torque with lower top speed)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Browsing pages 67 to the end in &lt;a href=&quot;http://www.sdp-si.com/PDFS/Technical-Section-Timing.pdf&quot;&gt;this document&lt;/a&gt; indicate that given our 108 Ncm peak torque a 6mm belt wouldn’t do it and a 15mm one would be more than enough. We are using a very short belt so our length correction factor is ~0.7 and to account for beginner errors I am just going to go for the beefier option.&lt;/p&gt;

&lt;p&gt;Once we have our choice of pulleys we need to calculate the belt length. Since the math is a bit more involved for that I provide a calculator below which does the heavy lifting.&lt;/p&gt;

&lt;style type=&quot;text/css&quot;&gt;table td{text-align: right;}table {margin: 0;}table.legend td{text-align: left;}&lt;/style&gt;
&lt;form name=&quot;frmCalc&quot;&gt; &lt;script src=&quot;/assets/js/BeltCalc.js&quot;&gt;&lt;/script&gt; &lt;table align=&quot;center&quot;&gt; &lt;tr&gt; &lt;td&gt;&lt;img alt=&quot;Belt Length-Center Distance Calculator&quot; src=&quot;/assets/img/pedal-car/pulleys.png&quot; /&gt;&lt;/td&gt;&lt;td&gt;&lt;table class=&quot;legend&quot;&gt; &lt;tr&gt; &lt;td&gt;D=Pitch Diameter Large Pulley&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt; &lt;td&gt;d=Pitch Diameter Small Pulley&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt; &lt;td&gt;C=Center Distance&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt; &lt;td&gt;L=Belt Pitch Length&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt; &lt;td&gt; &lt;table&gt; &lt;tr&gt; &lt;th&gt;Center Distance Known&lt;/th&gt; &lt;/tr&gt;&lt;tr&gt; &lt;td align=&quot;right&quot;&gt;Large Pulley D: &lt;input id=&quot;LP1&quot; name=&quot;LP1&quot; size=&quot;6&quot; value=&quot;120&quot; /&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt; &lt;td align=&quot;right&quot;&gt;Small Pulley d: &lt;input id=&quot;SP1&quot; name=&quot;SP1&quot; size=&quot;6&quot; value=&quot;22&quot; /&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt; &lt;td align=&quot;right&quot;&gt;Center Distance C: &lt;input id=&quot;CD1&quot; name=&quot;CD1&quot; size=&quot;6&quot; value=&quot;75&quot; /&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt; &lt;td align=&quot;right&quot;&gt;Belt Length: &lt;input id=&quot;length&quot; name=&quot;length&quot; size=&quot;6&quot; readonly=&quot;&quot; /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt; &lt;td&gt; &lt;input id=&quot;btnCalcL&quot; name=&quot;btnCalcL&quot; value=&quot;Calc&quot; onclick=&quot;calcLen()&quot; type=&quot;button&quot; /&gt; &lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;/td&gt;&lt;td&gt; &lt;table&gt; &lt;tr&gt; &lt;th&gt;Belt Length Known&lt;/th&gt; &lt;/tr&gt;&lt;tr&gt; &lt;td align=&quot;right&quot;&gt;Large Pulley D: &lt;input id=&quot;LP2&quot; name=&quot;LP2&quot; size=&quot;6&quot; /&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt; &lt;td align=&quot;right&quot;&gt;Small Pulley d: &lt;input id=&quot;SP2&quot; name=&quot;SP2&quot; size=&quot;6&quot; /&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt; &lt;td align=&quot;right&quot;&gt;Belt Length L: &lt;input id=&quot;BL2&quot; name=&quot;BL2&quot; size=&quot;6&quot; /&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt; &lt;td&gt;Center Distance: &lt;input id=&quot;cendis&quot; name=&quot;cendis&quot; size=&quot;6&quot; readonly=&quot;&quot; /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt; &lt;td&gt; &lt;input id=&quot;btnCalcC&quot; name=&quot;btnCalcC&quot; value=&quot;Calc&quot; onclick=&quot;calcCD()&quot; type=&quot;button&quot; /&gt; &lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;/td&gt;&lt;/tr&gt; &lt;/table&gt;&lt;/form&gt;

&lt;p&gt;In my case, 405mm is close enough to a standard belt size but I’m getting a 408mm belt to make sure it can be mounted.&lt;/p&gt;

&lt;h3 id=&quot;servo-steering&quot;&gt;Servo steering&lt;/h3&gt;

&lt;p&gt;I am thinking to implement remote control so I need to be able to steer the car. I am just going to do it like they do it on RC cars, with a servo motor.&lt;/p&gt;

&lt;p&gt;Basically a servo motor it’s special because it can rotate or push to a specific angle or distance and then keep that position steady. To do that it has a positive feedback loop which compares the input signal which specifies the position, with the actual position and tries to keep them in sync.
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/pedal-car/servo-principle.png&quot; alt=&quot;Servo principle&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Generally, servos are controlled with PWM at 50Hz and rotate 180 degrees.&lt;/p&gt;

&lt;p&gt;They tend to have high torque because they have a gear reduction mechanism but I’m getting one which is way bigger than the ones used for RC cars because the car is much bigger. I’ll use a SUPER200 servo which is rated for 200Kg/cm which means it can lift 200Kg at 1cm distance from the shaft. If the lever which moves the wheels is mounted 20cm away from the shaft I still get 10Kg of force to move the wheels so that’s good.
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/pedal-car/super200.png&quot; alt=&quot;SUPER200&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;quick-cad-modeling&quot;&gt;Quick CAD modeling&lt;/h3&gt;

&lt;p&gt;I believe I have pretty good imagination and I can see in my mind how things fit together. That was a problem in the past because there are always differences from reality so I decided to do a little bit of modeling to confirm all would fit together.&lt;/p&gt;

&lt;p&gt;Errors were visible right away so look at the image below.
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/pedal-car/motor-placement-error.png&quot; alt=&quot;CAD model shows error&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;The large timing pulley cuts in the dark blue metal plate which supports the motor near one of the edges which supports it. I will try to mount the motor 180 degrees rotated so the metal plate would have better structural integrity.&lt;/li&gt;
  &lt;li&gt;The two timing pulleys collide. I would have to make the metal brackets which support the motor narrower so I can place the motor 10mm closer to the back edge.&lt;/li&gt;
  &lt;li&gt;The small timing pulley rubs on the motor. I will mount it 2mm offset on the shaft and hope one of the sides will not fall off. I don’t want to use a thinner pulley because we determined earlier 15mm would do it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After putting a bit more thought into it, this assembly makes more sense like this:
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/pedal-car/motor-placement2.png&quot; alt=&quot;CAD model angle1&quot; /&gt;
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/pedal-car/motor-placement3.png&quot; alt=&quot;CAD model angle2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;To view the actual 3D assembly click &lt;a href=&quot;https://cad.onshape.com/documents/241a676fdc4eb44257fb0ab8/w/1c4bd2b4f504dc68d0085b1f/e/fbfca0cebc135ea93248fcd5&quot;&gt;HERE&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;bom-for-this-conversion&quot;&gt;BOM for this conversion&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;pedal car&lt;/li&gt;
  &lt;li&gt;GR 63X25 DC motor&lt;/li&gt;
  &lt;li&gt;24V battery pack&lt;/li&gt;
  &lt;li&gt;motor speed controller&lt;/li&gt;
  &lt;li&gt;10A fuse&lt;/li&gt;
  &lt;li&gt;acceleration pedal&lt;/li&gt;
  &lt;li&gt;threaded rod as a drive train&lt;/li&gt;
  &lt;li&gt;20T &amp;amp; 120T HTD3M timing pulleys&lt;/li&gt;
  &lt;li&gt;408mm timing belt (15mm wide)&lt;/li&gt;
  &lt;li&gt;SUPER200 servo&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We’re getting close to 300$ in parts, without considering the cost of the car.&lt;/p&gt;

&lt;p&gt;… I’ll think about it.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Operating Systems hidden on your PC</title>
   <link href="/security/2017/11/16/the-other-operating-systems-which-run-on-your-computer.html"/>
   <updated>2017-11-16T00:00:00+00:00</updated>
   <id>/security/2017/11/16/the-other-operating-systems-which-run-on-your-computer</id>
   <content type="html">&lt;p&gt;Whether you use a Mac or PC with Windows or Linux, your Intel computer runs some other operating systems in the background without bothering you with this piece of information. These OSs run all the time, have amazing capabilities and are impossible to remove.&lt;/p&gt;

&lt;p&gt;Some time ago, computer scientists devised a mechanism called &lt;a href=&quot;https://en.wikipedia.org/wiki/Protection_ring&quot;&gt;protection rings&lt;/a&gt; which has the purpose of allowing operating systems limit access to resources. It goes from ring 0 (most privileges) to ring 3 (least privileges). For example, the kernel of your operating system runs at ring 0 and your web browser at ring 3. The kernel should have the capability to access all the RAM to allocate it to different programs, but your web browser should not be able to read the memory of your bitcoin wallet software.&lt;/p&gt;

&lt;p&gt;Then it came hardware virtualization and that hypervisor runs one level below the kernel so that the guest OS can run just as before. We call this ring -1.&lt;/p&gt;

&lt;p&gt;Bellow ring -1 there are many other things lurking in the shadows.
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/firmware-trojan.jpg&quot; alt=&quot;UEFI Boot&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;system-management-mode-smm&quot;&gt;System Management Mode (SMM)&lt;/h3&gt;

&lt;p&gt;This is a special operating mode of your CPU, which runs code from the firmware completely independent of the Operating System. Some people call this ring -2.&lt;/p&gt;

&lt;p&gt;It does things such as:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;control fans or shut down the computer when the CPU overheats&lt;/li&gt;
  &lt;li&gt;resume the OS from standby when the laptop lid is open&lt;/li&gt;
  &lt;li&gt;emulate a USB keyboard as PS/2 so it can be used in a super legacy OS like DOS&lt;/li&gt;
  &lt;li&gt;control voltage regulators to manage how much power your CPU gets&lt;/li&gt;
  &lt;li&gt;vendors use it to implement features specific to their devices&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/SMM.jpg&quot; alt=&quot;UEFI Boot&quot; /&gt;&lt;/p&gt;

&lt;p&gt;SMM was designed so it can’t be overwritten by the main OS when it’s enabled and it reserves 8MB of RAM which is not visible anymore.&lt;/p&gt;

&lt;p&gt;SMM runs the vendor code all the time and you can’t do much about it. You don’t see what and when it runs and it has excellent control over USB or other peripherals.&lt;/p&gt;

&lt;p&gt;The code that runs in SMM takes time away from applications and in current implementations, it switches all the cores even to add 1+1.&lt;/p&gt;

&lt;p&gt;But of course, you should trust your vendor will do a good job here. It’s not like &lt;a href=&quot;https://leaksource.wordpress.com/2013/12/30/nsas-ant-division-catalog-of-exploits-for-nearly-every-major-software-hardware-firmware/&quot;&gt;NSA exploited SMM&lt;/a&gt; against the most reputable vendors like Dell, HP and Juniper.&lt;/p&gt;

&lt;h3 id=&quot;unified-extensible-firmware-interface-uefi&quot;&gt;Unified Extensible Firmware Interface (UEFI)&lt;/h3&gt;

&lt;p&gt;The word “extensible” sounds good in general, but not so good for things you want to be specific, simple and secure.&lt;/p&gt;

&lt;p&gt;This is a piece of software that replaces the BIOS which has some limitations such as it can only run in 16bit mode, address 1MB of memory and use up to 2TB drives. The specification was originally developed by Intel but in 2005 this responsibility was transferred to the &lt;a href=&quot;http://www.uefi.org/members&quot;&gt;UEFI Forum&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The main features of UEFI I would like to debate are:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;CPU independent device drivers&lt;/li&gt;
  &lt;li&gt;The possibility to run EFI applications&lt;/li&gt;
  &lt;li&gt;Graphical features which allow having a GUI before loading the OS&lt;/li&gt;
  &lt;li&gt;Network booting (PXE)&lt;/li&gt;
  &lt;li&gt;Secure Boot&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This list of advantages sounds like having an Operating System?!&lt;/p&gt;

&lt;p&gt;Let’s take this great features one at a time:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Universal drivers should be a great feature. I speculate that many of these drivers could be used by the main OS directly through the UEFI API. The truth is this most often they are implemented twice; once for firmware and once for the OS.&lt;/li&gt;
  &lt;li&gt;The application I willingly run is the GRUB boot loader which gives me flexibility when I start my operating system. I can’t think of anything more that I would want to run at this stage so I can’t appreciate this capability too much.&lt;/li&gt;
  &lt;li&gt;I don’t really need anything before I load the OS. I only need my OS to load fast so I wouldn’t mind a couple of seconds of black screen before the kernel of my OS initializes the display.&lt;/li&gt;
  &lt;li&gt;Network booting is a neat feature. I have also used it in the days of the BIOS when network cards had &lt;a href=&quot;https://en.wikipedia.org/wiki/Option_ROM&quot;&gt;a dedicated chip&lt;/a&gt; which included the software implementation for doing that. This feature allowed me to either run stateless machines without HDDs or to automatically install the OS without handling CDs. My concern now is that in the context of UEFI, this means an obscure application can communicate over the network and applications now are not limited like they used to be.&lt;/li&gt;
  &lt;li&gt;Secure boot is complete bullshit! It was mostly used by Microsoft to restrict people to only use the Windows which comes preinstalled. It restricts the firmware to only load a kernel signed with a private key which corresponds to a public key which is loaded in the firmware.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now let me tell you another concept. In UEFI there are &lt;strong&gt;boot services&lt;/strong&gt; and &lt;strong&gt;runtime services&lt;/strong&gt;. The boot services run until your operating starts loading and runtime services run also when your OS is running.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/UEFI-Boot.gif&quot; alt=&quot;UEFI Boot&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Most of UEFI is closed source and only the vendor knows what’s there. Some parts of it are OpenSource but basically that &lt;a href=&quot;https://github.com/tianocore/tianocore.github.io/wiki/EDK-II-Platforms&quot;&gt;doesn’t make a difference for the end user&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In a nutshell, UEFI is an extremely complex proprietary kernel which runs on the main CPU even while your OS is running. Exploits &lt;a href=&quot;https://www.cylance.com/en_us/blog/uefi-ransomware-full-disclosure-at-black-hat-asia.html&quot;&gt;where demonstrated&lt;/a&gt; this year which work even when updates and security measures are in place.&lt;/p&gt;

&lt;h3 id=&quot;intel-management-engine-intel-me&quot;&gt;Intel Management Engine (Intel ME)&lt;/h3&gt;

&lt;p&gt;This is the masterpiece. RING -3&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It is a separate processor core embedded in the CPU package, with internal ROM, RAM and DMA (direct memory access) to the main system memory.&lt;/strong&gt; In addition to that, it &lt;strong&gt;has network access&lt;/strong&gt; with its own MAC address through the ethernet controller.&lt;/p&gt;

&lt;p&gt;When you apply power, the first thing that starts is ME, which loads its firmware from the flash chip where you usually also have the UEFI firmware and SMM stuff. Parts of this firmware are signed by Intel and if it doesn’t find what it expects it either doesn’t start the main CPU or it reboots the computer every 30 minutes.&lt;/p&gt;

&lt;p&gt;One &lt;em&gt;nice&lt;/em&gt; component of ME is Active Management Technology (AMT) which &lt;strong&gt;can be used remotely even when the PC is turned off&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Another &lt;em&gt;nice&lt;/em&gt; one is Protected Audio Video Path (PAVP) which allows ME to communicate with the GPU so it can read and write to the screen. I wonder about the audio capabilities which are hinted in the name.&lt;/p&gt;

&lt;p&gt;In a nutshell, ME is the &lt;em&gt;nicest&lt;/em&gt; control tool which runs a proprietary MINIX based OS that can do everything on your computer:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;power ON/OFF&lt;/li&gt;
  &lt;li&gt;access all memory&lt;/li&gt;
  &lt;li&gt;view/paint your screen&lt;/li&gt;
  &lt;li&gt;read your keystrokes&lt;/li&gt;
  &lt;li&gt;… ?!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Having so &lt;em&gt;nice&lt;/em&gt; features it was surely bound to be &lt;a href=&quot;https://www.intel.com/content/www/us/en/architecture-and-technology/intel-amt-vulnerability-announcement.html&quot;&gt;vulnerable for 9 years&lt;/a&gt;. If you have an i3, i5 or i7 computer bought before the end of 2017 then &lt;strong&gt;you are likely vulnerable&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you want to know more, in the &lt;a href=&quot;https://www.intel.com/content/dam/www/public/us/en/documents/datasheets/9-series-chipset-pch-datasheet.pdf&quot;&gt;PCH datasheet&lt;/a&gt; at chapter 5.25 you can see a short overview. The PCH is the die on the right side of the image below.
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/broadwell-u.jpg&quot; alt=&quot;UEFI Boot&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;can-we-do-something-about-it&quot;&gt;Can we do something about it?&lt;/h3&gt;

&lt;p&gt;Technically speaking, the options are very limited. 
All these &lt;em&gt;beautiful things&lt;/em&gt; are burned on a flash chip like this one you can see on the right side of the CPU in my PC.
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/ThinkPad-X1.jpg&quot; alt=&quot;UEFI Boot&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In theory, we could do the following:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Disable parts of ME with &lt;a href=&quot;https://github.com/intel/INTEL-SA-00075-Linux-Detection-And-Mitigation-Tools&quot;&gt;this Linux tool&lt;/a&gt; or &lt;a href=&quot;https://downloadcenter.intel.com/download/26754&quot;&gt;the Windows one&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Buy a SPI flash programmer to dump all the firmware.&lt;/li&gt;
  &lt;li&gt;Use &lt;a href=&quot;https://github.com/corna/me_cleaner&quot;&gt;me_cleaner&lt;/a&gt; to remove a good part of the ME firmware.&lt;/li&gt;
  &lt;li&gt;Flash the minimized firmware back to that chip.&lt;/li&gt;
  &lt;li&gt;Hope for the best&lt;/li&gt;
  &lt;li&gt;To improve the UEFI and SMM issue, it’s going to be much harder. You’ll have to learn about &lt;a href=&quot;https://github.com/osresearch/heads&quot;&gt;heads&lt;/a&gt;, &lt;a href=&quot;https://www.coreboot.org/&quot;&gt;coreboot&lt;/a&gt;, the UEFI specifications. Then you’ll have to build a custom UEFI of your own which will start a Linux kernel very early on (at BDS stage). This kernel would take a good chunk of the EFI responsibility and it could also run your Linux OS. For me, it will be a little more difficult because I have 32bit UEFI and it would only start a 32bit kernel which I could then use to start the main OS kernel.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;… or maybe I will just buy a &lt;a href=&quot;https://puri.sm/&quot;&gt;Purism&lt;/a&gt; computer next time.&lt;/p&gt;

&lt;p&gt;If you are a Windows or MAC user, I think your only option is to complain to the government. Spreading awareness is something that I am sure you can do.&lt;/p&gt;

&lt;p&gt;We only talked about Intel here but AMD does something similar. Chromebooks are a little less affected by this but they only run Google stuff.&lt;/p&gt;

&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;Most of us are always running a version of MINIX on their computers, which &lt;a href=&quot;http://www.cs.vu.nl/~ast/intel/&quot;&gt;makes Tanenbaum very happy&lt;/a&gt; because MINIX is used more than Windows, Linux or MacOS.&lt;/p&gt;

&lt;p&gt;To access AMT you can use the user “admin” with an empty password and you have complete control. The right janitor in the wrong network would make  a very interesting story.&lt;/p&gt;

&lt;p&gt;We also run UEFI and SMM stuff all the time which was proven to be exploited very effectively &lt;a href=&quot;https://www.cylance.com/en_us/blog/uefi-ransomware-full-disclosure-at-black-hat-asia.html&quot;&gt;time&lt;/a&gt; and &lt;a href=&quot;https://leaksource.files.wordpress.com/2013/12/nsa-ant-ironchef.jpg&quot;&gt;time&lt;/a&gt; again.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Basic function generators</title>
   <link href="/electronics/2017/11/06/basic-function-generators.html"/>
   <updated>2017-11-06T00:00:00+00:00</updated>
   <id>/electronics/2017/11/06/basic-function-generators</id>
   <content type="html">&lt;p&gt;If you have electronics as a hobby it’s unlikely you are going to get away without using a function generator. Its role is to make electrical waveforms over a range of frequencies while allowing to control the amplitude of the waveform. Some basic use cases include testing speakers or amplifiers, calculating inductance for coils or experimenting with resonant circuits such as for wireless energy transfer, induction heating or tesla coils. In some cases, I got away without spending a cent but at some point I got a 10$ kit and a while later I spent 50$ for a finished product. A “normal” generator starts from 300$ so what exactly is inside the 50$ one?&lt;/p&gt;

&lt;h3 id=&quot;specs-to-consider&quot;&gt;Specs to consider&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;https://upload.wikimedia.org/wikipedia/commons/0/09/Format_te_ndryshme_valore.gif&quot; alt=&quot;waveforms&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Waveform types&lt;/strong&gt; should be at least sine, square, triangle. Sawtooth and reverse sawtooth can also be useful but an ARB generator will do everything.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Frequency range&lt;/strong&gt;: I would be satisfied with 0.1Hz-1MHz but if you only play with audio applications pretty much any generator would cover the range.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;DC Offset&lt;/strong&gt; is not really a must-have feature but I would be happy if I could add +5V DC offset to the signal. For example, it would help to fake digital signals.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Duty cycle control&lt;/strong&gt; is often used to control the power supplied through MOSFETs. For example, with PWM I am adjusting the &lt;a href=&quot;/diy/2017/10/12/flashlight-with-software.html&quot;&gt;light level in a flashlight&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Output level&lt;/strong&gt; represents the maximum and minimum level of the signal. If it does 10Vpp then you can have +/-5V signals and it would cover a lot.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Output impedance&lt;/strong&gt; is 50 Ohm standard but with crappy generators is larger. If the impedance is larger it would have less driving capability for a load.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Modulation&lt;/strong&gt; would come handy if you plan to do more advanced experiments. Amplitude, frequency and phase modulation are the common types.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;analog-or-digital&quot;&gt;Analog or digital&lt;/h3&gt;

&lt;p&gt;If we want to do it in less than a day, analog is the best option. We should be able to do it with a few components and for very little money. The first chip that comes to my mind is XR-2206 and in &lt;a href=&quot;https://ia802704.us.archive.org/12/items/ExarFunctionGeneratorDataBook/ExarFunctionGeneratorDataBook.pdf&quot;&gt;its databook&lt;/a&gt; from more than 30 years ago, you can see some good notes starting with page 42. The other one I am thinking about is &lt;a href=&quot;https://www.intersil.com/content/dam/Intersil/documents/icl8/icl8038.pdf&quot;&gt;ICL8038&lt;/a&gt; and this one has the advantage of being readily available in my parts bin.&lt;/p&gt;

&lt;p&gt;They are both designed for generating signals and I guess with a dual opamp, three potentiometers, some caps and resistors will be all done. Half of the dual opamp I could use as a summing amplifier for offset and the other half as a buffer. The potentiometers would be frequency, amplitude and offset.&lt;/p&gt;

&lt;p&gt;This approach with &lt;strong&gt;analog would be fun, easy, quick and cheap but lacking&lt;/strong&gt; in some areas. It wouldn’t be easy to precisely set the frequency, not high frequency and having two channels in sync with controllable phase shift is not easy with these. Not to mention they are not being manufactured anymore.&lt;/p&gt;

&lt;p&gt;Buying a decent analog generator is not really attractive to me because it’s bulky and I live in an apartment.&lt;/p&gt;

&lt;p&gt;With a digital generator, we dial in exactly the frequency that we want. Coupled with some simple software it can sweep between two frequencies in a predefined amount of time or even generate some arbitrary waveforms with the fancier ones. These unlock a lot of other possibilities and are by far the most common commercial function generators these days.&lt;/p&gt;

&lt;p&gt;Out of the digital type, the most common ones use &lt;a href=&quot;http://www.analog.com/en/analog-dialogue/articles/all-about-direct-digital-synthesis.html&quot;&gt;direct digital synthesis&lt;/a&gt;, DDS. They are very versatile but of course more complicated and more expensive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DDS uses a phase accumulator, a look-up table containing a digital representation of the waveform, and a DAC. The phase accumulator advances position each time it receives a clock pulse. This position in the look-up table contains a digital value that is feed in a DAC.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.analog.com/-/media/images/analog-dialogue/en/volume-38/number-3/articles/all-about-direct-digital-synthesis/dds_fig-05.gif?la=en&quot; alt=&quot;DDS architecture&quot; /&gt;&lt;/p&gt;

&lt;p&gt;As a DIY approach, I would probably consider using &lt;a href=&quot;http://www.analog.com/media/en/technical-documentation/data-sheets/AD9833.pdf&quot;&gt;AD9833&lt;/a&gt; which is not expensive and would allow me to generate signals up to a few MHz. I would add a second one for having two channels, some Arduino compatible board, a nice LCD, rotary encoder and plenty buttons to make it easier to jump to the functionality we care about. I don’t like instruments where you spend time navigating through menus. Of course, just like before we need the opamps for controlling the offset or amplifying the signal.&lt;/p&gt;

&lt;h3 id=&quot;the-free-generator&quot;&gt;The free generator&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/Smartphone-function-gen.jpg&quot; alt=&quot;Smartphone function generator&quot; /&gt;
Yeah, it’s just a jack cable which I hook to my phone where I run the &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.keuwl.functiongenerator&quot;&gt;Function Generator Android App&lt;/a&gt;.
&lt;img src=&quot;https://lh3.googleusercontent.com/ReFp0Tk2zFkZyRJFLHvWiRuB7jxKibmruhOEPT52FhzpByAXDM2QT7XUDu5CaTG1NsqU=h900&quot; alt=&quot;Function Generator Android&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Sacrifice a pair of old headphones and you got yourself a dual channel function generator for free.
Its sample rate is bad, the output level is horrible and there is no DC offset but you can’t beat this price point.
This thing is just good enough to test audio stuff and it can be set up in no time.&lt;/p&gt;

&lt;h3 id=&quot;the-10-kit&quot;&gt;The 10$ kit&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/DDS-Kit-new.jpg&quot; alt=&quot;DDS Kit&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I got this mostly because I felt like building a kit and I imagine it would come in handy at some point. I like its design for its simplicity but I don’t enjoy using it because it’s awkward to operate. It didn’t come with a power supply so I adapted the picoPSU I’ve had around. The power supply was way more expensive than the kit!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/DDS-Kit.jpg&quot; alt=&quot;DDS Kit&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The design of this seems to be copied from &lt;a href=&quot;http://www.scienceprog.com/avr-dds-signal-generator-v20/&quot;&gt;ScienceProg&lt;/a&gt;.
&lt;img src=&quot;http://www.electronics-lab.com/wp-content/uploads/2015/04/Schematic.png&quot; alt=&quot;DDS Kit schematic&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The Atmega16 micro generates signals which go in an 8bit &lt;a href=&quot;https://en.wikipedia.org/wiki/Resistor_ladder&quot;&gt;R-2R DAC&lt;/a&gt; that then goes in an OpAmp for setting the amplitude and offset.&lt;/p&gt;

&lt;p&gt;Its frequency range (0-65KHz) and output levels (10Vpp) are a few times better than the Android generator but I ended up using the Android generator way more than this. Without having it in a proper case with buttons it’s just not fun to use.&lt;/p&gt;

&lt;h3 id=&quot;the-50-unit&quot;&gt;The 50$ unit&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/DDS-MHS-5200A.jpg&quot; alt=&quot;MHS-5200A&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It comes fully assembled as a product, packed in a cardboard box, with charger and some cables for 50$ including shipping from China! Its specs are impressive to me:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;0.01Hz-25MHz for sine and up to 6MHz for the other waves&lt;/li&gt;
  &lt;li&gt;5mVpp~20Vpp amplitude&lt;/li&gt;
  &lt;li&gt;12 bits amplitude resolution&lt;/li&gt;
  &lt;li&gt;Arbitrary waveforms with memory for my own&lt;/li&gt;
  &lt;li&gt;PC control over USB&lt;/li&gt;
  &lt;li&gt;… and the list goes on and on&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How is this possible?! What’s inside?&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/DDS-MHS-5200A-board.gif&quot; alt=&quot;MHS-5200A PCB&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It’s actually got quite a few things which are not necessarily the cheapest if we got 1000 of them from a reliable supplier like DigiKey or Mouser.&lt;/p&gt;

&lt;p&gt;From left to right:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;There is the switching power supply which converts 5V to +13V and to -13V.  &lt;strong&gt;~ 1$&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Next to the power supply it’s the ST 8bit, 16MHz microcontroller which most likely handles the LCD, menu and all that user interaction. &lt;strong&gt;&amp;lt; 1$&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Bellow the power supply it’s the USB-SERIAL converter which allows us to talk to the micro and an EEPROM for storing ARB waveforms and settings. &lt;strong&gt;&amp;lt; 0.3$&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Then it’s the &lt;a href=&quot;http://www.latticesemi.com/~/media/LatticeSemi/Documents/DataSheets/MachXO23/MachXO2FamilyDataSheet.pdf&quot;&gt;Lattice MachX02&lt;/a&gt; FPGA which is one of the cheaper ones but still one of the most expensive single chips from this board. &lt;strong&gt;&amp;lt; 6$&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;The R-2R resistor ladder is a good way to make two DACs without spending money. When a 12bit DAC is implemented, 0.1% resistors should be used but here cost is the driving force so normal resistors were used. &lt;strong&gt;&amp;lt; 0.1$&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Then the signal flows in the two &lt;a href=&quot;http://www.analog.com/media/en/technical-documentation/data-sheets/AD8017.pdf&quot;&gt;AD8017&lt;/a&gt; variable gain amplifiers. &lt;strong&gt;&amp;lt; 6$&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Just before these but not in the signal path there are two LM OpAmps which control the DC Offset. These are super cheap. &lt;strong&gt;~ 0.1$&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Last, under the &lt;em&gt;way too small&lt;/em&gt; heatsink there are the most expensive chips. Those are the output buffers which actually drive the load that we hook up to our generator. My board had &lt;a href=&quot;http://www.ti.com/lit/ds/symlink/ths4022.pdf&quot;&gt;THS4022&lt;/a&gt; which are pretty high-speed chips so at 25MHz the sine was still looking good. &lt;strong&gt;&amp;gt; 12$&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Quicky adding these up, then making some very optimistic estimations for PCB, connectors, plastic case, LCD, power adaptor, cables, cardboard box and labor it probably goes to a minimum of &lt;strong&gt;35$&lt;/strong&gt; for the &lt;a href=&quot;https://en.wikipedia.org/wiki/Cost_of_goods_sold&quot;&gt;cost of goods sold&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This also shows that both resellers and manufacturers operate on very thin profit margins. I am sure they pay less than my estimations and I would really learn how they do that.&lt;/p&gt;

&lt;h5 id=&quot;improvements-i-did&quot;&gt;Improvements I did&lt;/h5&gt;

&lt;ul&gt;
  &lt;li&gt;Replace &lt;a href=&quot;http://www.ti.com/lit/ds/symlink/ths4022.pdf&quot;&gt;THS4022&lt;/a&gt; with &lt;a href=&quot;http://www.ti.com/lit/ds/symlink/ths3092.pdf&quot;&gt;THS3092&lt;/a&gt; which is slightly cheaper and can handle more current. This means we maintain the amplitude better at higher frequencies.&lt;/li&gt;
  &lt;li&gt;Replace the heatsink with a much larger one. At high frequency or with low impedance loads this thing gets hot.&lt;/li&gt;
  &lt;li&gt;Add some decoupling capacitors on the input of the power supply to remove some noise. On my board I added 1600uF and it was enough for medium loads.&lt;/li&gt;
  &lt;li&gt;Add a small heatsink to the &lt;a href=&quot;http://www.ksmcu.com/pdf/XL6007%20datasheet.pdf&quot;&gt;XL6007&lt;/a&gt; switching converter. This works at the very limit of its output current when the generator is driven hard. In it’s SEPIC topology it should do 0.6A but the OpAmps want way more.&lt;/li&gt;
  &lt;li&gt;Blocked the light from the LCD to bleed to the LEDs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5 id=&quot;improvements-i-wish-the-manufacturer-did&quot;&gt;Improvements I wish the manufacturer did&lt;/h5&gt;

&lt;ul&gt;
  &lt;li&gt;Much better SEPIC converter. This implementation can’t handle enough current.&lt;/li&gt;
  &lt;li&gt;OpenSource software. I am sure nobody can make it cheaper so if the software was OpenSource people would be happy to improve it. For example, I don’t see why this unit wouldn’t support modulation.&lt;/li&gt;
  &lt;li&gt;Better load handling.&lt;/li&gt;
  &lt;li&gt;Lower noise.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;a-professional-generator-board&quot;&gt;A professional generator board&lt;/h3&gt;

&lt;p&gt;Sigilent &lt;a href=&quot;https://www.siglent.eu/waveform-generators/sdg-5000-series.html&quot;&gt;SDG 5000&lt;/a&gt; series are entry level arbitrary waveform generators which might actually be used in a professional environment. This one is more than $500 and as you can see below, the main board is way more complex. The obvious things are a fancier FPGA, SRAM, a nice DAC and many OpAmps in parallel on the output.&lt;/p&gt;

&lt;p&gt;&lt;a data-flickr-embed=&quot;true&quot; href=&quot;https://www.flickr.com/photos/eevblog/9356134720/in/album-72157634773277340/&quot; title=&quot;SAM_9773&quot;&gt;&lt;img src=&quot;https://farm4.staticflickr.com/3696/9356134720_bfe3b1dae9_h.jpg&quot; width=&quot;1600&quot; height=&quot;1200&quot; alt=&quot;SAM_9773&quot; /&gt;&lt;/a&gt;&lt;script async=&quot;&quot; src=&quot;//embedr.flickr.com/assets/client-code.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;Another board does only the software and control stuff and this one is also quite impressive to me.&lt;/p&gt;

&lt;p&gt;&lt;a data-flickr-embed=&quot;true&quot; href=&quot;https://www.flickr.com/photos/eevblog/9353362203/in/album-72157634773277340/&quot; title=&quot;SAM_9769&quot;&gt;&lt;img src=&quot;https://farm4.staticflickr.com/3770/9353362203_5e5f2d000b_h.jpg&quot; width=&quot;1600&quot; height=&quot;1200&quot; alt=&quot;SAM_9769&quot; /&gt;&lt;/a&gt;&lt;script async=&quot;&quot; src=&quot;//embedr.flickr.com/assets/client-code.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;&lt;/p&gt;

&lt;h3 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Function generators can be fun :)&lt;/li&gt;
  &lt;li&gt;As usual, you get what you pay for so don’t get the 10$ Kit.&lt;/li&gt;
  &lt;li&gt;The 50$ MHS-5200A unit is good bang for the buck and with some small improvements and OpenSource firmware, it can be even better.&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Flashlight with software</title>
   <link href="/diy/2017/10/12/flashlight-with-software.html"/>
   <updated>2017-10-12T00:00:00+00:00</updated>
   <id>/diy/2017/10/12/flashlight-with-software</id>
   <content type="html">&lt;p&gt;So, you know when you are tired or bored and you go to strange places online? I somehow found this flashlight online and from the picture, you can see &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;many high power LEDs&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;many high power batteries&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;adequate cooling&lt;/code&gt; =&amp;gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;awesome light output&lt;/code&gt;. The price at that time was ~50$ so I ordered because it seemed I get a lot for my money.&lt;/p&gt;

&lt;p&gt;As a technical guy, I see 10x CREE XM-L T6 and I go straight to &lt;a href=&quot;http://www.cree.com/led-components/media/documents/XLampXML-11E.pdf&quot;&gt;the datasheet&lt;/a&gt; to see what that is about. It looks like one LED is able to output 692 lumens at 2A and 3.2V. This is the rated power but the datasheet also suggests it can be overdriven too, so I could speculate one of these LEDs can reach 1000 lumens. 10 of these would output 10000 lumens and they would consume either MANY amps (in parallel) or volts (in series).&lt;/p&gt;

&lt;p&gt;Anyways, from the theoretical (not the advertised) specs it looks like a 100W LED flashlight which can output 10.000 lumens. This should be great.&lt;/p&gt;

&lt;p&gt;I ordered, it arrived, and &lt;strong&gt;it wasn’t great&lt;/strong&gt;. The light output was not impressive so I disassembled it to see what’s up.&lt;/p&gt;

&lt;h3 id=&quot;principle-of-operation&quot;&gt;Principle of operation&lt;/h3&gt;

&lt;p&gt;All those LEDs are in parallel so to reach max output it should draw more than 20A and that’s insane. That’s also at the very limit of the 4 parallel 18650 cells but I guess in theory it should be OK to go to maximum for a few seconds. A quick measurement revealed it draws under 1A, so something is clearly not right.&lt;/p&gt;

&lt;p&gt;Looking at the electronics we can quickly deduce it works like this:
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/Flashlight-driver-original.jpg&quot; alt=&quot;Flashlight driver hacked&quot; /&gt;&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Pressing the button is registered by the microcontroller.&lt;/li&gt;
  &lt;li&gt;The microcontroller switches the MOSFET on/off. By changing the amount of time the FET is ON vs OFF the light output can be controlled.&lt;/li&gt;
  &lt;li&gt;Some resistors limit the current flow between batteries, MOSFET and LEDs.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;more-is-less&quot;&gt;More is less&lt;/h3&gt;

&lt;p&gt;The first thing to try is shunting those resistors so more current will flow to the LEDs. I can immediately see the light is way brighter and now it’s drawing around 3A. It’s not even close to the expected maximum not now at least is nice.&lt;/p&gt;

&lt;p&gt;I played with it for a little more and &lt;strong&gt;suddenly it was dead&lt;/strong&gt;. No smoke or something like that, it just didn’t work anymore.&lt;/p&gt;

&lt;p&gt;Probing the circuit a little I was able to determine the microcontroller was faulty. If it was the MOSFET then I could easily replace that and get it working. The microcontroller had no markings and I had no software to flash to it anyway. Before I abandon this I decided to hook the LEDs directly to the bench power supply to see how much light can these actually deliver and it seems not more than 4A. It seems the &lt;strong&gt;LEDs are also fake&lt;/strong&gt;. :)&lt;/p&gt;

&lt;p&gt;I clearly didn’t get what I paid for.&lt;/p&gt;

&lt;h3 id=&quot;less-is-more&quot;&gt;Less is more&lt;/h3&gt;

&lt;p&gt;One year has passed, and that weekend when I made time to do something different arrived.&lt;/p&gt;

&lt;p&gt;The footprint of an ATtiny13 matches what used to be on that board so I incorrectly assumed it should fit right in.
Reality is that it doesn’t even match the VCC and GND pins but it’s OK; we cut a few traces, bypass with a few wires and we make it work.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://camo.githubusercontent.com/b621cdf0625c6a9e961bb3ac5c94c46198f7585d/687474703a2f2f692e696d6775722e636f6d2f4a7362677550562e6a7067&quot; alt=&quot;ATtiny13 pinout&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Basically, we need to power the ATtiny13, connect the MOSFET to a pin that can be used for PWM (pin 5 or 6) and the button to a digital IO pin which is pretty much any other pin.&lt;/p&gt;

&lt;p&gt;I made this simple programming rig where I used an Arduino nano as an ISP and connected a button and an LED to the ATtiny13.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/ATtiny13-programming-rig.jpg&quot; alt=&quot;ATtiny13 programming rig&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;code&quot;&gt;Code&lt;/h4&gt;

&lt;p&gt;All I want from this flashlight is to be able to control the light intensity.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I keep the button pressed from Off and the light starts ramping up.&lt;/li&gt;
  &lt;li&gt;I keep the button pressed from On and the light reverses until it turns off.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s easy to use for everyone and easy to implement.&lt;/p&gt;

&lt;p&gt;I have an array of 16 intensity values which should be somehow logarithmic since perception of light is not linear. We go through those every 100ms and when you lift the finger of the button light stays at that level.&lt;/p&gt;

&lt;p&gt;Initially, the array had 64 values for much smoother ramping but ATtiny13 doesn’t have enough RAM for that. :)&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/bogdanr/9cf92b924f3d03c737be438d1379dc0b.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;The signal that is sent to the MOSFT when the button is pressed looks like this:
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/Flashlight-10T6-scope.gif&quot; alt=&quot;Flashlight demo&quot; /&gt;&lt;/p&gt;

&lt;p&gt;With this code, the microcontroller works all the time it’s powered. Fortunately this micro is not power hungry.&lt;/p&gt;

&lt;p&gt;Just as a quick and easy power saving method I disable the ADC and the Analog comparator to save 25% energy and if I configure it to work at 1.2MHz instead of the default 9.6MHz. This cuts the energy consumption in half once more. It now uses under 1mA so it’s good enough for now.&lt;/p&gt;

&lt;h3 id=&quot;end-result&quot;&gt;End result&lt;/h3&gt;

&lt;p&gt;After fitting our new microcontroller on our board, it looks like this:
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/Flashlight-driver-hacked.jpg&quot; alt=&quot;Flashlight driver hacked&quot; /&gt;&lt;/p&gt;

&lt;p&gt;… and the end result looks like this:
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/Flashlight-10T6-demo.gif&quot; alt=&quot;Flashlight demo&quot; /&gt;
I actually press the button twice. Once to go to max and again to go from max to zero.&lt;/p&gt;

&lt;p&gt;YEAH! The flashlight is alive again!&lt;/p&gt;

&lt;h3 id=&quot;possible-improvements&quot;&gt;Possible improvements&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Read the battery voltage with the ADC and reduce the output or produce a warning strobe when the voltage is too low.&lt;/li&gt;
  &lt;li&gt;When the flashlight is off power down the microcontroller and wake it up with an interrupt when the button is pressed. This would improve the standby time a little.&lt;/li&gt;
  &lt;li&gt;Automatically reduce the output from 100% to 50% after a number of minutes. This should help a lot with heat and battery life.&lt;/li&gt;
  &lt;li&gt;Go hardcore and make another board which can accommodate more MOSFETs for better power dissipation, temperate sensor and ATtiny85 which has more memory.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since the flashlight is usable now, I am going to stop here but if I was to develop a product, I would definitely do those improvements.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Power meter for the entire apartment</title>
   <link href="/diy/2017/04/19/apartment-energy-monitor.html"/>
   <updated>2017-04-19T00:00:00+00:00</updated>
   <id>/diy/2017/04/19/apartment-energy-monitor</id>
   <content type="html">&lt;p&gt;In the weekend I wanted to do something fun for improving the visibility of energy consumption. I ended up with a nice LED display that shows usage in realtime and some cool charts on my phone.&lt;/p&gt;

&lt;h3 id=&quot;principle-of-operation&quot;&gt;Principle of operation&lt;/h3&gt;

&lt;p&gt;We learned in middle school that current passing through a wire generates a magnetic field and that a magnetic field passing through a wire generates electricity. Later I learned that this is the basic principle of &lt;a href=&quot;https://en.wikipedia.org/wiki/Transformer&quot;&gt;the transformer&lt;/a&gt;. &lt;a href=&quot;https://en.wikipedia.org/wiki/Current_clamp#Current_transformer&quot;&gt;Our current sensor is essentially a transformer&lt;/a&gt; which generates a voltage across a burden resistor proportional to the current passing through the wire we are clamping the sensor to.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/Current-transformer.gif&quot; alt=&quot;Current transformer&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Now we need to read the voltage from the sensor and do some calculations to determine the power usage.&lt;/p&gt;

&lt;p&gt;Since our voltage is AC, it has negative values and we would have to add a DC offset to it so the alternation would only happen above zero.
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/DC-offset.jpg&quot; alt=&quot;Current clamp circuit&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Our microcontroller has an ADC which would convert the voltage value to a numerical value depending on it’s resolution. A 10bit resolution could have a value between 0-1023.&lt;/p&gt;

&lt;p&gt;Finally, the circuit going to our ADC looks something like this:
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/AC-current-input.png&quot; alt=&quot;Current clamp circuit&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;implementation&quot;&gt;Implementation&lt;/h3&gt;

&lt;p&gt;Our BOM (Bill of materials) is short and cheap (~$20):&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Microcontroller&lt;/strong&gt;: Wemos D1 mini&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://learn.openenergymonitor.org/electricity-monitoring/ct-sensors/introduction&quot;&gt;&lt;strong&gt;CT Sensor&lt;/strong&gt;&lt;/a&gt;: YHDC SCT-013-000&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Display&lt;/strong&gt;: Dot matrix with MAX7219 driver&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Power supply&lt;/strong&gt;: HLK-PM03&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Yeah, I am a fan of the &lt;a href=&quot;http://bogdan.nimblex.net/diy/2016/10/29/iot-fuzzy-clock.html&quot;&gt;ESP8266&lt;/a&gt; microcontroller even though it doesn’t have the best ADC. Still, it has WiFi and works well with the Arduino SDK.&lt;/p&gt;

&lt;p&gt;To determine the burden resistor for the CT sensor &lt;strong&gt;we have two options&lt;/strong&gt;:&lt;/p&gt;
&lt;h5 id=&quot;do-some-math&quot;&gt;Do some math&lt;/h5&gt;

&lt;ol&gt;
  &lt;li&gt;Assuming we want to measure up to 9kW then the peak current would be: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;9000/230=39.13 ~ 40A&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Since we have AC, we have to multiply with √2 to get peak values: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;40A × 1.414 = 55.33A&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Our sensor is rated 50mA on the secondary for 100A on the primary so we have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;100 x 1000 / 50 = 2000&lt;/code&gt; turns.&lt;/li&gt;
  &lt;li&gt;The peak current we can expect on the secondary will be: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;55.33A / 2000 = 0.0276A&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Now the burden resistor should be chosen so that voltage doesn’t go over half of 3.3V: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3.3 V / 2 / 0.0276 A = 59.7 Ω&lt;/code&gt;
This is close to 56Ω which is a &lt;a href=&quot;https://ecee.colorado.edu/~mcclurel/resistorsandcaps.pdf&quot;&gt;common value&lt;/a&gt; so we can choose that.&lt;/li&gt;
&lt;/ol&gt;

&lt;h5 id=&quot;do-some-measurements&quot;&gt;Do some measurements&lt;/h5&gt;

&lt;p&gt;Took out the old scope and measured Vpp with various burden resistors and with all the major appliances running. ;)
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/Power-usage-scope.jpg&quot; alt=&quot;Energy monitor oscilloscope&quot; /&gt;
WTF is this?! &lt;a href=&quot;https://learn.openenergymonitor.org/electricity-monitoring/ac-power-theory/introduction&quot;&gt;Where is my sine wave&lt;/a&gt;?! Yeah, with all those reactive and non-liner loads (Fridge, TV, CFL and LED bulb, computers, etc) it will not look like a sine wave. If I plug everything off and only run the stove or some other resistive load it looks like a very pretty sine wave but with normal devices, never.&lt;/p&gt;

&lt;p&gt;It seems that the sweetspot is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2 x 47Ω&lt;/code&gt; and adding all the running appliances sums up to ~6kW. I added a calibration feature in the Android app anyways and this way we could get slightly better results.&lt;/p&gt;

&lt;p&gt;After a bit of soldering and coding, our prototype looks like this:
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/Power-usage-prototype.jpg&quot; alt=&quot;Energy monitor prototype&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Here my meter is measuring 1525Wh and the commercial thing I have is measuring 1550Wh. The error margin is less than 2% so I’m happy with this result. We don’t know how well the commercial meter is calibrated anyways.&lt;/p&gt;

&lt;h4 id=&quot;code&quot;&gt;Code&lt;/h4&gt;

&lt;p&gt;The SDK we are going to use is Arduino and a bunch of libs that make things simple.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/blynkkk/blynk-library/releases/&quot;&gt;Blynk&lt;/a&gt; will help us with the Andorid app and communications through Internet.&lt;/li&gt;
  &lt;li&gt;ArduinoOTA will allow us to do wireless firmware updates.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/nickgammon/MAX7219_Dot_Matrix&quot;&gt;MAX7219_Dot_Matrix&lt;/a&gt; is obviously the lib which &lt;em&gt;paints&lt;/em&gt; the display.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/openenergymonitor/EmonLib&quot;&gt;EmonLib&lt;/a&gt; does all the math for energy monitoring.&lt;/li&gt;
&lt;/ul&gt;

&lt;script src=&quot;https://gist.github.com/bogdanr/907f819876231cc2fc72b5f727ffe68c.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;After the prototype testing I installed it in the fuse box and it looks like this:
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/Power-usage-installed.gif&quot; alt=&quot;Energy monitor installed&quot; /&gt;&lt;/p&gt;

&lt;p&gt;… and the Android app looks like this:
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/Power-usage-android.jpg&quot; alt=&quot;Energy monitor android&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;possible-improvements&quot;&gt;Possible improvements&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Add more channels.&lt;/li&gt;
  &lt;li&gt;Improve the resolution.&lt;/li&gt;
  &lt;li&gt;Predict the cost.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The ESP8266 has a single 1V, 10bit ADC built in. This isn’t great if you want precision. Using an external ADC such as &lt;a href=&quot;http://www.ti.com/lit/ds/symlink/ads1113.pdf&quot;&gt;ADS1115&lt;/a&gt; would allow us to go to 4 channels, 5V and 16 bit. It would be a huge step up and just a small increase in cost.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Hacking the washing machine</title>
   <link href="/diy/2017/04/11/hacking-the-washing-machine.html"/>
   <updated>2017-04-11T00:00:00+00:00</updated>
   <id>/diy/2017/04/11/hacking-the-washing-machine</id>
   <content type="html">&lt;p&gt;I got the perfect washing machine in my early 20s when I was single. It has some predefined programs, no display or any other complicated features. I was using mostly “power + quick wash”. Now, in my early 30s, my wife uses programs that take hours and staring them after work means the cycle would be done after midnight. So, let’s make that hunk of metal controllable from the Internet.&lt;/p&gt;

&lt;h3 id=&quot;step-1---understand-how-it-works&quot;&gt;Step 1 - Understand how it works&lt;/h3&gt;

&lt;p&gt;At first impression all is simple. It’s a relatively unknown micro with many GPIOs, some used as inputs for buttons and some to switch transistors that drive LEDs.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/Indesit-sixl-cb1.jpg&quot; alt=&quot;Indesit SIXL control board&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I got the control board out from the machine and hooked it to a bench power supply but nothing happens. Obviously there is also a power module with relays and stuff for controlling valves and the motor. It turns out that on this power module there is an EPROM which identifies the model and which allows the control board to actually run. That is not going to be an issue because we can test with the complete circuit.&lt;/p&gt;

&lt;p&gt;Probing around with the multimeter made it clear quickly that the buttons pull GPIOs to GND. LEDs on the other hand, are NOT connected to GND or to a voltage rail directly through a resistor. The LEDs are connected to GND through individual transistors and power is applied to all of them through another transistor.&lt;/p&gt;

&lt;p&gt;Doing a bit more investigation, seems that there are a lot of failsafe mechanisms so the machine wouldn’t run with a jammed engine or failed valves. Still, we don’t care about all that so we move on.&lt;/p&gt;

&lt;h3 id=&quot;step-2---interface-a-wireless-microcontroller&quot;&gt;Step 2 - Interface a wireless microcontroller&lt;/h3&gt;

&lt;p&gt;Our microcontroller of choice is going to be the notorious &lt;a href=&quot;http://bogdan.nimblex.net/diy/2016/10/29/iot-fuzzy-clock.html&quot;&gt;ESP8266&lt;/a&gt; for obvious reasons; it has builtin WiFi, it’s cheap, easily available and works well with easy to use SDKs such as Arduino. It has some minor shortcomings, such as it’s logic is 3.3V while the micro in the washing machine is 5V. That it’s easy to overcome with some simple voltage dividers or a level shifter circuit so we move on.&lt;/p&gt;

&lt;p&gt;We just want to do two simple things:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Push buttons to actually start wash cycles.&lt;/li&gt;
  &lt;li&gt;Read LEDs so that we know remotely the state of the machine.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If we only did the button pushing thing then we would have no guaranty things are actually happening.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;For pushing the buttons we will connect some transistors to ESP8266 and use them as a second set of switches. This will use 3 GPIOs and handle Power, the 40°C program and the 60°C program.&lt;/li&gt;
  &lt;li&gt;For reading the LEDs I decided to use a &lt;a href=&quot;http://cdn.sparkfun.com/datasheets/BreakoutBoards/Logic_Level_Bidirectional.pdf&quot;&gt;level shifter&lt;/a&gt; I had around. We will use all the 4 channels to detect the power, lock, 40° and 60° LEDs.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It would be a good idea to improve the 5V power supply included in the power module because our microcontroller draws extra 100mA and the added consumption takes us very close to the limit. Still, I will do that some other day.&lt;/p&gt;

&lt;h3 id=&quot;code&quot;&gt;Code&lt;/h3&gt;

&lt;p&gt;The SDK we are going to use is Arduino and with just a library or two this is going to be really simple.&lt;/p&gt;

&lt;p&gt;Blink will help us with the Andorid app and communications with the microcontroller through Internet.&lt;/p&gt;

&lt;p&gt;WiFiManager will help us not hardcode the AP credentials in the code so that when we change the wireless router, we don’t have to reflash the washing machine.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/bogdanr/1bc97fd0326df7570b609393dae8477e.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;After some testing with the ESP8266 disconnected I procedded to solder it in and it now looks like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/Indesit-sixl-cb2.jpg&quot; alt=&quot;Indesit Moon hack&quot; /&gt;
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/Indesit-sixl-cb3.jpg&quot; alt=&quot;Indesit Moon hack installed&quot; /&gt;&lt;/p&gt;

&lt;p&gt;… and the Android app looks like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/Indesit-sixl-app.gif&quot; alt=&quot;Blynk washing machine&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;step-3---enjoy&quot;&gt;Step 3 - Enjoy&lt;/h3&gt;

&lt;p&gt;To me, this is still the best washing machine because I don’t have to buy a new one :)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/Indesit-sixl.jpg&quot; alt=&quot;Indesit Moon hack&quot; /&gt;&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Automating SurveyMonkey Responses</title>
   <link href="/automation/2017/03/24/automating-surveymonkey-responses.html"/>
   <updated>2017-03-24T00:00:00+00:00</updated>
   <id>/automation/2017/03/24/automating-surveymonkey-responses</id>
   <content type="html">&lt;p&gt;I wanted to give &lt;a href=&quot;http://www.seleniumhq.org&quot;&gt;Selenium&lt;/a&gt; a try for a while and I just found the perfect pretext:
earn enough votes in a SurveyMonkey poll to win a bottle of cognac.&lt;/p&gt;

&lt;h3 id=&quot;constrains&quot;&gt;Constrains&lt;/h3&gt;

&lt;p&gt;The automation has to work on SurveyMonkey because this was the chosen poll system. After some initial checking it was clear this one has some security checks in place so that makes it even more fun.&lt;/p&gt;

&lt;h3 id=&quot;why-this-works&quot;&gt;Why this works&lt;/h3&gt;

&lt;p&gt;We will instantiate an incognito browser every time so cookies will not be saved and we can run this over and over again. This will be a real browser which will receive simulated clicks on HTML elements so it will be hard to detect it’s automated.&lt;/p&gt;

&lt;p&gt;Also, SurveyMonekey has an option to check if voting is done from the same IP address. In this case the option was not used so unfortunately this was quite easy.&lt;/p&gt;

&lt;h3 id=&quot;code&quot;&gt;Code&lt;/h3&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;time&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;selenium&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;webdriver&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;selenium.webdriver.common.keys&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Keys&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;selenium.webdriver.chrome.options&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Options&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;chrome_options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;webdriver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ChromeOptions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;chrome_options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;-incognito&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;n&quot;&gt;driver&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;webdriver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Chrome&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;executable_path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;/usr/lib64/chromium/chromedriver&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;chrome_options&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chrome_options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;driver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;https://www.surveymonkey.com/r/YD6G9PT&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vote_check&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;driver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find_element_by_xpath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;.//*[@id=&apos;question-field-96043893&apos;]/fieldset/div/div/div[1]/div/label/span[1]&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vote_check&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;click&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;vote_done&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;driver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find_element_by_xpath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;//button[contains(text(), &apos; Done&apos;)]&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vote_done&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;click&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;driver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;quit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Obviously you have to replace the survey URL and the ID of the question. &lt;a href=&quot;http://selenium-python.readthedocs.io/locating-elements.html&quot;&gt;HERE&lt;/a&gt; you can find a starting point regarding how we locate the clickable elements.&lt;/p&gt;

&lt;p&gt;Installing selenium is easy with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip3 install selenium&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And to run it, all you have to do is: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python3 win.py&lt;/code&gt;&lt;/p&gt;

&lt;h4 id=&quot;before-applying-jerk-script&quot;&gt;Before applying jerk script&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/SurveyMonkey-before.png&quot; alt=&quot;SurveyMonkey - Before&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;after-applying-jerk-script&quot;&gt;After applying jerk script&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/SurveyMonkey-after.png&quot; alt=&quot;SurveyMonkey - After&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;wear-protection&quot;&gt;Wear protection&lt;/h3&gt;

&lt;p&gt;It seems there is an option to send the survey by email, and not by a web link. If you send the survey by email you are doing two things:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;You are giving SurveyMonkey the email address of your respondents (&lt;strong&gt;not cool&lt;/strong&gt;)&lt;/li&gt;
  &lt;li&gt;You are allowing SurveyMonkey to generate links for each email address (&lt;strong&gt;cool&lt;/strong&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;h5 id=&quot;notes&quot;&gt;Notes:&lt;/h5&gt;

&lt;p&gt;I actually ran the automation after the winner was chosen.&lt;/p&gt;

&lt;p&gt;It works well in March 2017 but it’s likely it will have to be adjusted at some point if SurveyMonkey will make changes to their system.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Benchmarking Cloud VMs</title>
   <link href="/cloud/2017/01/05/benchmarking-cloud-vms.html"/>
   <updated>2017-01-05T00:00:00+00:00</updated>
   <id>/cloud/2017/01/05/benchmarking-cloud-vms</id>
   <content type="html">&lt;p&gt;Once in a while I compare the performance vs cost benefits of cloud vendors. In this case I just need to compare virtual machines, which is by far the most used service out there, so I guess sharing these results should be useful to many people.&lt;/p&gt;

&lt;h3 id=&quot;constrains&quot;&gt;Constrains&lt;/h3&gt;

&lt;p&gt;I am automating things are a pretty high degree so the vendors I am looking at should have a decent API that would allow me to create and destroy servers without ever going into the web admin interface.&lt;/p&gt;

&lt;p&gt;I only care about compute for this project so we are only comparing that. There will be no added value if a vendor has features that we don’t use.&lt;/p&gt;

&lt;h3 id=&quot;methodology&quot;&gt;Methodology&lt;/h3&gt;

&lt;p&gt;By analyzing the offerings, I will choose some vendors and an instance type that is equivalent and the most cost effective.&lt;/p&gt;

&lt;p&gt;Thus, the chosen instance size was 8G RAM and 4 vCPUs and the vendors are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Amazon Web Services&lt;/li&gt;
  &lt;li&gt;Google Compute Engine&lt;/li&gt;
  &lt;li&gt;Digital Ocean&lt;/li&gt;
  &lt;li&gt;Linode&lt;/li&gt;
  &lt;li&gt;Scaleway&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will test, CPU, Disk IO, memory and network bandwidth.&lt;/p&gt;

&lt;h4 id=&quot;environment&quot;&gt;Environment&lt;/h4&gt;

&lt;p&gt;All tests would be done on Debian 8 because it has fairly recent tooling and it’s a popular and well maintained distro.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apt-get install fio sysbench ioping&lt;/code&gt;&lt;/p&gt;

&lt;h4 id=&quot;disk&quot;&gt;Disk&lt;/h4&gt;

&lt;p&gt;All the instances had 100G SSD attached. Performance will vary significantly here because they use different technologies.&lt;/p&gt;

&lt;h5 id=&quot;random-rw&quot;&gt;Random RW&lt;/h5&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fio --ioengine=libaio --direct=1 --bs=4k --iodepth=64 --size=5G --rw=randrw --gtod_reduce=1 --name=rw&lt;/code&gt;&lt;/p&gt;

&lt;h5 id=&quot;random-read&quot;&gt;Random Read&lt;/h5&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fio --ioengine=libaio --direct=1 --bs=4k --iodepth=64 --size=5G --rw=randread --gtod_reduce=1 --name=read&lt;/code&gt;&lt;/p&gt;

&lt;h5 id=&quot;random-write&quot;&gt;Random Write&lt;/h5&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fio --ioengine=libaio --direct=1 --bs=4k --iodepth=64 --size=5G --rw=randwrite --gtod_reduce=1 --name=write&lt;/code&gt;&lt;/p&gt;

&lt;h4 id=&quot;cpu&quot;&gt;CPU&lt;/h4&gt;

&lt;p&gt;We are running the tests with a different number of threads in order to observe if performance scales well as we increase the number of cores.&lt;/p&gt;

&lt;p&gt;These tests should be repeated a few hours apart to determine observe if the CPU performance looks predictable or if there is a big chance for noisy neighbors.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;for each in 1 2 4; do sysbench --test=cpu --cpu-max-prime=20000 --num-threads=$each run|grep &quot;execution time&quot;; done&lt;/code&gt;&lt;/p&gt;

&lt;h4 id=&quot;memory&quot;&gt;Memory&lt;/h4&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sysbench --test=memory --num-threads=4 run | grep &quot;execution time&quot;&lt;/code&gt;&lt;/p&gt;

&lt;h4 id=&quot;bandwidth&quot;&gt;Bandwidth&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;On machine A
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iperf -s -p 81&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;On machine B
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iperf -c 10.150.0.146 -i 1 -t 60 -V -p 81&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;results&quot;&gt;Results&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/cloud-performance/CPU-Pi.png&quot; alt=&quot;CPU time to compute large Pi&quot; /&gt;
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/cloud-performance/MySQL.png&quot; alt=&quot;MySQL Performance&quot; /&gt;
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/cloud-performance/Network.png&quot; alt=&quot;Internal Network Speed&quot; /&gt;
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/cloud-performance/IOperformance.png&quot; alt=&quot;IO Performance&quot; /&gt;
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/cloud-performance/RAM.png&quot; alt=&quot;RAM Performance&quot; /&gt;
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/cloud-performance/Cost.png&quot; alt=&quot;Cost&quot; /&gt;&lt;/p&gt;

&lt;h5 id=&quot;notes&quot;&gt;Notes:&lt;/h5&gt;

&lt;p&gt;Amazon and Google both limit IO performance according to disk size. They both can perform very well with way more expensive storage.
Scaleway offers a very interesting cloud offering with both physical and virtual servers. I tested both and each one is OK for a different job.&lt;/p&gt;

&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions:&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;There is a huge difference in the cloud offering.&lt;/li&gt;
  &lt;li&gt;Compute at Amazon is very expensive compared with others.&lt;/li&gt;
  &lt;li&gt;I chose Linode in this case because peformance is really good at it’s price point.&lt;/li&gt;
  &lt;li&gt;Out of these 5 vendors Scaleway seems the cheapest as of January 2017, but it depends on what do you need. To achive such a low cost they use commodity hardware with Atom CPUs but that is fine since it’s reflected in the price.&lt;/li&gt;
  &lt;li&gt;Remember that in the cloud, CPUs, RAM, disks are not created equal.&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Testing charge-pump ICs</title>
   <link href="/diy/2016/12/08/testing-charge-pump-ics.html"/>
   <updated>2016-12-08T00:00:00+00:00</updated>
   <id>/diy/2016/12/08/testing-charge-pump-ics</id>
   <content type="html">&lt;p&gt;Sometimes we need a negative voltage rail. There are several ways to obtain that but most likely the easiest is to use a charge-pump IC with only two capacitors.
Because the datasheet doesn’t always paint a clear picture I decided to order a few and do my own testing for the things I care about (current, ripple, switching frequency).&lt;/p&gt;

&lt;h3 id=&quot;application&quot;&gt;Application&lt;/h3&gt;

&lt;p&gt;I suppose that you already have an application in mind since you are reading this. Nevertheless, this time my use case is powering up OpAmps which I will use in an audio application. Is might not work well for this but that’s what I want to find out.&lt;/p&gt;

&lt;p&gt;Charge pumps are essentially integrated in almost all flash-memory and they are instrumental in deleting data. As standalone devices they are not common place.&lt;/p&gt;

&lt;h3 id=&quot;possible-issues&quot;&gt;Possible issues&lt;/h3&gt;

&lt;p&gt;Let’s see quickly how they work. In the image below we can see that we essentially have 4 switches.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/charge-pump.gif&quot; alt=&quot;charge pump&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Closing S1 and S3 charges C1 in the first half cycle. In the second half, S1 and S3 open and S2 and S4 close. C1 is then in parallel with the reservoir capacitor C2. If the voltage across C2 is smaller than that across C1, charge flows from C1 to C2 until the voltage equalizes. Since the polarity is inverted then the voltage would be negative.&lt;/p&gt;

&lt;p&gt;The more current you draw from C2 the more ripple you’ll observe. The frequency of the ripple will be the frequency at which the switches operate.&lt;/p&gt;

&lt;p&gt;For powering OpAmps this is clearly not ideal because charge pumps are switching devices which, of course, have ripple on the output. On the other hand, OpAmps have a &lt;a href=&quot;https://en.wikipedia.org/wiki/Power_supply_rejection_ratio&quot;&gt;PSRR&lt;/a&gt; (power supply rejection ratio) which define how much of the noise from the power supply will end up in the output of the OpAmp.&lt;/p&gt;

&lt;p&gt;In the image below we have a generic graph for PSRR.
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/PSRR.png&quot; alt=&quot;charge pump&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This essentially tells us that at 10kHz the rejection of noise from the negative supply is ~ 105 dB. This means that if you have 10 kHz ripple on the negative supply, the noise would be 0.000005 of the audio signal. Even if we amplify the signal 10x it’s still going to be great. Nevertheless, this is OP4177 which has a great PSRR. For many other OpAmps we don’t even have this data in the datasheet so we just need to do some tests and see for ourselves.&lt;/p&gt;

&lt;p&gt;It looks great. Even with 100x worse PSRR it should still be good enough.&lt;/p&gt;

&lt;p&gt;Also, I have another plan. If we can use the charge pump at greater than audible frequencies then we could probably even ignore this data. A young and super pretentious teenager should be able to hear all the way up to 20kHz. Once you get older you don’t hear high frequencies well anymore. Because I was never a &lt;em&gt;golden ear&lt;/em&gt; I will count on measurements.&lt;/p&gt;

&lt;p&gt;In short:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Large ripple + bad PSRR =&amp;gt; noisy output.&lt;/li&gt;
  &lt;li&gt;Small ripple at high frequency + decent PSRR =&amp;gt; happiness&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;change-pump-ics&quot;&gt;Change pump ICs&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/766x.jpg&quot; alt=&quot;charge pump ICs&quot; /&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Intersil &lt;a href=&quot;http://www.intersil.com/content/dam/intersil/documents/icl7/icl7660s-a.pdf&quot;&gt;7660S&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;Microcip &lt;a href=&quot;http://ww1.microchip.com/downloads/en/DeviceDoc/21465C.pdf&quot;&gt;TC7660&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;Linear &lt;a href=&quot;http://cds.linear.com/docs/en/datasheet/1144fa.pdf&quot;&gt;LTC1144&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;Misterion 7662&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;I am interested in testing the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;maximum current they can dump in a 100 Ohm resistor when supplied with 8V&lt;/li&gt;
  &lt;li&gt;ripple while loaded with the 100 Ohm resistor&lt;/li&gt;
  &lt;li&gt;operating frequency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some of these have a boost functionality that can increase the operating frequency so I will also test this where available.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Intersil &lt;a href=&quot;http://www.intersil.com/content/dam/intersil/documents/icl7/icl7660s-a.pdf&quot;&gt;7660S&lt;/a&gt;&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Microcip &lt;a href=&quot;http://ww1.microchip.com/downloads/en/DeviceDoc/21465C.pdf&quot;&gt;TC7660&lt;/a&gt;&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Linear &lt;a href=&quot;http://cds.linear.com/docs/en/datasheet/1144fa.pdf&quot;&gt;LTC1144&lt;/a&gt;&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Misterion 7662&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;37mA&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;41mA&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;36mA&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;31mA&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;1.6V&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;1.0V&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;1.3V&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;1.5V&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;3kHz&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;6kHz&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;3kHz&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;2kHz&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;We have some pretty picture too, taken with the scope. You can say which is which by looking at the Vpp and frequency values.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/scope/ICL7662.png&quot; alt=&quot;ICL7662&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The doubled waveform is obviously a trigger error captured by the scope.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/scope/TC7660.png&quot; alt=&quot;TC7660&quot; /&gt;
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/scope/LTC1144-boost.png&quot; alt=&quot;LTC 1144 without boost&quot; /&gt;
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/scope/unk-boost.png&quot; alt=&quot;unk-boost&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Out of the bunch, the last two also had a boost function which would increase the switching frequency. That should have also been available for Intersil 7660S but it didn’t work. Perhaps I had a fake of defective batch.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Linear &lt;a href=&quot;http://cds.linear.com/docs/en/datasheet/1144fa.pdf&quot;&gt;LTC1144&lt;/a&gt; + boost&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Misterion 7662 + boost&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;30mA&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;30mA&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0.7V&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;1.2V&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;37kHz&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;2.7kHz&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/scope/LTC1144+boost.png&quot; alt=&quot;LTC 1144 with boost&quot; /&gt;
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/scope/unk+boost.png&quot; alt=&quot;unk+boost&quot; /&gt;&lt;/p&gt;

&lt;p&gt;LTC1144 actually stats to look acceptable, especially compared with the others. It’s oscillating at much more higher frequencies than audible. Even though the ripple is huge, at least is much better than the others. I guess it makes sense now that is twice the cost of the next one in the bunch.&lt;/p&gt;

&lt;p&gt;Still, 700mV ripple is huge. According to the datasheet we should be able to do much better.&lt;/p&gt;

&lt;p&gt;At the bottom of page 7, &lt;a href=&quot;http://cds.linear.com/docs/en/datasheet/1144fa.pdf&quot;&gt;the datasheet&lt;/a&gt; tells us that capacitors are not critical. On the other hand they also show that most of the charts go up to 20mA, even though one goes up to 50mA.
Still, regular 10uF electrolytic caps have a pretty big ESR. At high frequencies, the resistance of the caps should greatly influence the transfer of energy from C1 to C2, thus it will increase the ripple and decrease the output current.&lt;/p&gt;

&lt;p&gt;Let’s test LTC1144 with 10uF capacitors that have much lower ESR.&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;Tantalun&lt;/td&gt;
      &lt;td&gt;Ceramic&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Current&lt;/td&gt;
      &lt;td&gt;40mA&lt;/td&gt;
      &lt;td&gt;39mA&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Ripple&lt;/td&gt;
      &lt;td&gt;0.8V&lt;/td&gt;
      &lt;td&gt;1.0V&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Freq&lt;/td&gt;
      &lt;td&gt;3kHz&lt;/td&gt;
      &lt;td&gt;3kHz&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Already a big difference even at the lower frequencies. Surely it would be better once we activate the boost function.&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;Tantalun&lt;/td&gt;
      &lt;td&gt;Ceramic&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Current&lt;/td&gt;
      &lt;td&gt;30mA&lt;/td&gt;
      &lt;td&gt;33mA&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Ripple&lt;/td&gt;
      &lt;td&gt;0.3V&lt;/td&gt;
      &lt;td&gt;0.16V&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Freq&lt;/td&gt;
      &lt;td&gt;37kHz&lt;/td&gt;
      &lt;td&gt;36kHz&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/scope/LTC1144+boost+ceramic.png&quot; alt=&quot;LTC 1144 with boost&quot; /&gt;&lt;/p&gt;

&lt;p&gt;That’s more like it! LTC1144 is the only decent charge pump for this job. With 10uF ceramic caps, it shows the best performance, even though that is not mentioned in the datasheet. Perhaps I am missing something but even so, tantalum caps are a much better option and they make a huge difference.&lt;/p&gt;

&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions:&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;The difference between pin compatible parts ca be huge.&lt;/li&gt;
  &lt;li&gt;The ESR of capacitors can be a huge influence in various applications.&lt;/li&gt;
  &lt;li&gt;Charge pumps could be a very decent option where low power is required.&lt;/li&gt;
  &lt;li&gt;LTC1144 is significantly more expensive than the bunch that was tested but it’s performance is much better.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One thing that was brought to my attention is that I didn’t mention the voltage drop is huge with our 100 Ohm load. After we account for the output resistance in our IC, &lt;strong&gt;if we put 8V in, we will get -3.3V out&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Unfortunately I think I need a few times more current than these can deliver for driving headphones decently. Even though I could parallel more charge pumps ICs, I will also consider LT1054. If that doesn’t work perhaps I will have to consider a switching power supply with an inductor.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>IoT Fuzzy Clock</title>
   <link href="/diy/2016/10/29/iot-fuzzy-clock.html"/>
   <updated>2016-10-29T00:00:00+00:00</updated>
   <id>/diy/2016/10/29/iot-fuzzy-clock</id>
   <content type="html">&lt;p&gt;Let’s see how to make a very precise clock that will be read with a large margin of error. It should be easy for the technically inclined and it can also be fun.&lt;/p&gt;

&lt;video src=&quot;/assets/img/FuzzyClock-timelapse.webm&quot; type=&quot;video/webm&quot; width=&quot;770&quot; controls=&quot;&quot; autoplay=&quot;&quot; loop=&quot;&quot;&gt;&lt;/video&gt;

&lt;p&gt;The purpose is to introduce some very versatile and yet cheap building blocks in the most straightforward way possible. It was written for beginners and it explains a bunch of things from scratch.&lt;/p&gt;

&lt;p&gt;Above you can see the green LED is the minute, the red one is the hour and the blue one indicates atmospheric pressure. It’s a 12 hour clock and in the time lapse it goes from ~ 5:10 to 6:50 PM. When the blue LED is close to the left there is a small chance of rain and when it’s close to the right there is a significant chance of rain.&lt;/p&gt;

&lt;h2 id=&quot;bom-bill-of-materials&quot;&gt;BOM (Bill of materials)&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;ESP8266 module&lt;/li&gt;
  &lt;li&gt;WS8211 LED strip&lt;/li&gt;
  &lt;li&gt;Any USB charger&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the time of the writing both the module and the LED strip could be purchased for under $10 online.
I would never recommend getting a cheap USB charger because it could burn down your house or create a lot of RF noise that could interfere with other stuff such as the WiFi signal.&lt;/p&gt;

&lt;h4 id=&quot;esp8266&quot;&gt;ESP8266&lt;/h4&gt;

&lt;p&gt;ESP8266 is a very cost effective chip that integrates WiFi with a capable microcontroller. We will be using a module that uses that chip along with flash so we could store our code and a voltage regulator so we can power it from 5V.&lt;/p&gt;

&lt;p&gt;I used &lt;a href=&quot;http://www.schatenseite.de/en/2016/04/22/esp8266-witty-cloud-module/&quot;&gt;the Witty board&lt;/a&gt; because I already had it lying around and because for this particular project it comes with an &lt;a href=&quot;https://en.wikipedia.org/wiki/Photoresistor&quot;&gt;LDR&lt;/a&gt; soldered on. I will use the LDR to detect the ambient light and control the intensity of the LEDs accordingly. You can get the module from &lt;a href=&quot;https://www.aliexpress.com/wholesale?SearchText=witty&quot;&gt;Aliexpress&lt;/a&gt; if you don’t have a faster alternative.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/ESP8266-Witty.jpg&quot; alt=&quot;ESP8266 Whitty&quot; /&gt;&lt;/p&gt;

&lt;h5 id=&quot;features&quot;&gt;Features&lt;/h5&gt;

&lt;ul&gt;
  &lt;li&gt;32-bit RISC CPU running at 80 MHz&lt;/li&gt;
  &lt;li&gt;64 KiB of instruction RAM, 96 KiB of data RAM&lt;/li&gt;
  &lt;li&gt;External &lt;a href=&quot;https://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus&quot;&gt;SPI&lt;/a&gt; flash - usually 4 MiB&lt;/li&gt;
  &lt;li&gt;IEEE 802.11 b/g/n Wi-Fi&lt;/li&gt;
  &lt;li&gt;UART on dedicated pins&lt;/li&gt;
  &lt;li&gt;16 &lt;a href=&quot;https://en.wikipedia.org/wiki/General-purpose_input/output&quot;&gt;GPIO&lt;/a&gt; pins&lt;/li&gt;
  &lt;li&gt;one 10-bit &lt;a href=&quot;https://en.wikipedia.org/wiki/Analog-to-digital_converter&quot;&gt;ADC&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;SPI, &lt;a href=&quot;https://en.wikipedia.org/wiki/I%C2%B2C&quot;&gt;I²C&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To see the beautiful piece of silicon &lt;a href=&quot;http://s.zeptobars.com/ESP8266-HD.jpg&quot;&gt;check out the work done by Zeptobars&lt;/a&gt;.&lt;/p&gt;

&lt;h4 id=&quot;ws2812b&quot;&gt;WS2812B&lt;/h4&gt;

&lt;p&gt;We are going to use an RGB LED strip with individually addressable LEDs. Different LED colors will indicate different things and the position on the strip will indicate a relative value.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/30led_strip.jpg&quot; alt=&quot;WS2812 LED strip&quot; /&gt;&lt;/p&gt;

&lt;p&gt;WS2812 is essentially a capsule which has red, green and blue LEDs connected directly to a chip. This makes it possible to digitally control 256 brightness levels for each color to obtain 16M colors. Depending on the version of the chip we could change colors 400-800 times per second. These can be cascaded and the signal would be sent through a one wire interface. In theory we could achieve 30fps with 1024 of these huge pixels. These work great at 5V, have reverse polarity protection and are very cost effective.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/ws2812.jpg&quot; alt=&quot;WS2812 die&quot; /&gt;&lt;/p&gt;

&lt;p&gt;For this project I plan to use only one color at a time and to change it every minute so we will be well under spec. For this application 60 LEDs would make the math easier because it divides nicely with 60 minutes or 12 hours. Nevertheless I only have 30 LEDs at hand so I am going to use that because we are making the fuzzy clock :)&lt;/p&gt;

&lt;h2 id=&quot;soldering&quot;&gt;Soldering&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://mightyohm.com/files/soldercomic/FullSolderComic_EN.pdf&quot;&gt;Soldering is easy&lt;/a&gt;. Connect the red wire (+5V) to VCC, the white wire to GND and the green wire (data in) to GPIO5. The signal travels in the direction of the arrow on the LED strip so just keep that in mind.&lt;/p&gt;

&lt;p&gt;Also add a small resistor (less than 1K) between GPIO16 and REST. This will bring the micro back to life then it’s done sleeping.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/FuzzyClockBoard.jpg&quot; alt=&quot;WS2812 die&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;software&quot;&gt;Software&lt;/h2&gt;

&lt;p&gt;ESP8266 works with quite a few different SDKs so it can be programmed using different languages. MicroPython is very nice if you like Python, NodeMCU for Lua, Arduino for C++ and there is even a firmware for BASIC. I played with all these and personally I prefer Arduino because it has libraries for almost everything. I also read the documentation for mongoose-iot but as of 2016 it’s just getting started. It also looks interesting but time will tell if it’s going to be an enterprise product or for everybody.&lt;/p&gt;

&lt;h4 id=&quot;arduino&quot;&gt;Arduino&lt;/h4&gt;

&lt;p&gt;Yeah, you all heard about this one. They are some people that like to fight who make some boards and an IDE.&lt;/p&gt;

&lt;p&gt;I like the boards that inspired a lot of people and because they were OpenSource it also became possible to get clones for much smaller prices. This inspired even more people. Hardware wise, I am not impressed with the boards. After all these years, I think they are still lacking in some areas.&lt;/p&gt;

&lt;p&gt;Now the IDE is a very different story. I think the IDE got better and better. There are many easy to use libraries out of the box. You can find a bunch of other libraries on the Internet. You can even use all these ecosystem for unofficially supported boards and that’s exactly what are we going to do.&lt;/p&gt;

&lt;p&gt;The IDE is written in Java so make sure you have JRE. It uses a library from the Wiring project to make it easy to interact with the pins of the microcontroller. It organizes the code in a minimum of two functions &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setup()&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;loop()&lt;/code&gt; which are pretty self explanatory. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setup()&lt;/code&gt; runs only once when the microcontroller is powered up and then &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;loop()&lt;/code&gt; runs continuously. The Blink sketch makes everything clear.&lt;/p&gt;

&lt;p&gt;Just remember that the Arduino IDE is &lt;strong&gt;not&lt;/strong&gt; only for Arduino boards.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/esp8266/Arduino#installing-with-boards-manager&quot;&gt;Installing with Boards Manager&lt;/a&gt; is usually the easiest to get started with ESP8266.&lt;/p&gt;

&lt;h4 id=&quot;code&quot;&gt;Code&lt;/h4&gt;

&lt;p&gt;The big picture is:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;We import libraries
    &lt;ul&gt;
      &lt;li&gt;ESP8266WiFi makes it easy to connect to WiFi and go to sleep&lt;/li&gt;
      &lt;li&gt;NTPtimeESP is an extension that gets us nicely formatted time&lt;/li&gt;
      &lt;li&gt;Adafruit_NeoPixel makes it easy to work with WS2812B LEDs&lt;/li&gt;
      &lt;li&gt;ArduinoJson helps us handle the JSON data that we get from an external API&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;We define a bunch of constants and variables&lt;/li&gt;
  &lt;li&gt;We only execute the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setup()&lt;/code&gt; function because we want to run things only once and then go to sleep for a little while. When we come back from sleep we reset the micro and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setup()&lt;/code&gt; function is executed again. This way, most of the time the microcontroller is actually powered down so it’s drawing very little energy.&lt;/li&gt;
  &lt;li&gt;Some functions are defined to make it a bit more readable
    &lt;ul&gt;
      &lt;li&gt;WUAPI connects to api.wunderground.com to get the barometric pressure for our city&lt;/li&gt;
      &lt;li&gt;showWeather formats the JSON weather data&lt;/li&gt;
      &lt;li&gt;getShowData retrieves data from NTP, calculates the position of the LEDs and lights them up. Yeah, this one is not very well structured but it is late and I want to finish this post.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;script src=&quot;https://gist.github.com/bogdanr/4e94e1d66e94aafd76a395677d022015.js&quot;&gt;&lt;/script&gt;

&lt;h2 id=&quot;possible-improvements&quot;&gt;Possible improvements&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;OTA (Over The Air) software upgrades&lt;/li&gt;
  &lt;li&gt;Add a buzzer and make a short sound every hour during the day&lt;/li&gt;
  &lt;li&gt;Add a visual or acoustic alarm that could be dismissed with a press of a button&lt;/li&gt;
  &lt;li&gt;Add a PIR sensor and trigger an alarm when a person’s presence is detected&lt;/li&gt;
  &lt;li&gt;Connect a HTU21D or a SHT10 temperature and humidity sensor and put the data in the cloud&lt;/li&gt;
  &lt;li&gt;Make it flash &lt;a href=&quot;http://www.ucapps.de/midibox_ng/rgb_leds.gif&quot;&gt;crazy beautiful colors&lt;/a&gt; for various anniversaries&lt;/li&gt;
  &lt;li&gt;Make it possible to adjust the timezone by pressing a button.&lt;/li&gt;
  &lt;li&gt;If it can’t connect to WiFi, go in STA mode so the user could connect to it and do to a web interface from where he could setup WiFi.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion:&lt;/h2&gt;

&lt;p&gt;I guess you could say this is a IoT project but let’s not say that because it doesn’t sound very nice. :)&lt;/p&gt;

&lt;p&gt;We are doing it this way because it’s much simpler than if we used an RTC. We don’t need to adjust the time. We don’t need to maintain power to maintain the time. We get daylight saving adjustments automatically.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Hacking Radio Remotes</title>
   <link href="/electronics/2015/08/24/hacking-radio-remotes.html"/>
   <updated>2015-08-24T00:00:00+00:00</updated>
   <id>/electronics/2015/08/24/hacking-radio-remotes</id>
   <content type="html">&lt;p&gt;Cheap wireless remotes are everywhere and the purpose of this article is to learn how most of them work, how secure they are and how to create your own in order to clone or extend an existing remote.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/rf_remotes.jpg&quot; alt=&quot;RF Remotes&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/ws2811_remote.jpg&quot; style=&quot;float: right; height: 200px&quot; /&gt;
The kind of remotes we are talking about are usually used for controlling lights, opening garage doors or gates, controlling thermostats or any other general purpose application. I hope in 2020 this article will be obsolete but in 2015 it works for 90% of the remotes.&lt;/p&gt;

&lt;p&gt;The remote we’ll use here comes from a pretty new product class, the RGB LED controllers for individually addressable WS8211 LEDs. My intuition tells me that in a few years more people are going to use these but let’s hope I’m wrong.&lt;/p&gt;

&lt;h2 id=&quot;capturing-the-signal&quot;&gt;Capturing the signal&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/RTL2832U_dongle.jpg&quot; style=&quot;float: left;&quot; /&gt;
For capturing the signal I used a RTL-SDR dongle (RTL2832U) which can be bough for about $10 from the Internet. Everybody who is familiar with software defined radios know them well. For everybody else it’s important to understand what’s SDR and how this dongle can be used. Software defined radio, SDR, is the implementation of some radio components such as modulators, demodulators, filters and amplifiers in software instead of hardware. Because of this, with the proper software and the right configuration we should be able to demodulate and decode pretty much any signal in the frequency range which can be received by our radio.&lt;/p&gt;

&lt;p&gt;A very important feature of our $10 dongle is that it’s frequency range is 24 - 1766 MHz. Within this range there are radio and TV signals as well as our remote signal, baby monitors, CB radios (such as those used by taxi) some GSM communication and a lot more. Nevertheless, my remote works on 433MHz and we’ll listen on that frequency.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/rf_remote_gqrx.png&quot; alt=&quot;gqrx&quot; /&gt;&lt;/p&gt;

&lt;p&gt;For software we have several options such as &lt;a href=&quot;http://sdr.osmocom.org/trac/wiki/rtl-sdr#Software&quot;&gt;rtl-sdr&lt;/a&gt;, &lt;a href=&quot;http://gnuradio.org&quot;&gt;GNURadio&lt;/a&gt; and &lt;a href=&quot;http://gqrx.dk&quot;&gt;gqrx&lt;/a&gt;. I prefer to use gqrx because it is very easy to tune precisely to the right frequency with it’s FFT plot and waterfall display. Also it can record the signal to a WAV file which we can then import in Audacity to analyze.&lt;/p&gt;

&lt;p&gt;Pressing a button on the remote while you are listening on 433MHz will show a strong signal on the waterfall display. You can now tune precisely on the right frequency. Another very common frequency is 315MHz and 90% of the remotes will use one of these. Also, the vast majority of these remotes use a form of &lt;a href=&quot;https://en.wikipedia.org/wiki/Amplitude_modulation&quot;&gt;amplitude modulation&lt;/a&gt; called &lt;a href=&quot;https://en.wikipedia.org/wiki/On-off_keying&quot;&gt;OOK&lt;/a&gt; so we need to select AM in the Mode dropdown box in gqrx. Pressing a button on the remote should now produce some high pitch sounds. Record a couple of those key presses so we can analyze the data that is being transmitted.&lt;/p&gt;

&lt;h2 id=&quot;decoding-the-signal&quot;&gt;Decoding the signal&lt;/h2&gt;

&lt;p&gt;For decoding those sounds we’ll use &lt;a href=&quot;http://audacityteam.org/&quot;&gt;Audacity&lt;/a&gt;. We need to import that wave file and zoom right into our signal. After you select Waveform (dB) for that channel, it should look a little bit like this: 
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/rf_remote_original.png&quot; alt=&quot;Original On/Off signal&quot; /&gt;
With the classical method of eyeballing we can easily determine these are some bits which are either high or low.* This is called &lt;a href=&quot;https://en.wikipedia.org/wiki/On-off_keying&quot;&gt;OOK&lt;/a&gt; modulation. Also by eye I translate this into bits. A fancy oscilloscope could do the translation automatically but I don’t have one so I’m going old school. The translated message looks like this: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;11100000000011101000111011101000100010001110100010001000100010001000111011101000 1000111010100011...&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;A huge part of this decoding is also figuring out the proper timing but it can easily be done in audacity. We need to zoom right to the smallest bit and measure it’s length. I prefer to go down to the samples level because that’s more precise.
&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/rf_remote_timing.png&quot; alt=&quot;Fabricated On/Off signal&quot; /&gt;
Here we can see that we recorded with a resolution of 48000 samples per second and that our bit has a length of 26 samples. With some quick math (1/48000*26) we determine that the bit lenght is 541 micorseconds.&lt;/p&gt;

&lt;h2 id=&quot;transmitting&quot;&gt;Transmitting&lt;/h2&gt;

&lt;p&gt;For this we need a 433MHz RF transmitter which supports &lt;a href=&quot;https://en.wikipedia.org/wiki/Amplitude-shift_keying&quot;&gt;ASK&lt;/a&gt; modulation and a microcontroller. For the microcontroller I used an Arduino Nano board because it’s easy to program. Connecting is just power, ground and a digital pin to the data line, and then you go straight to coding.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-C&quot;&gt;#define TX_PIN 3
#define BIT_PERIOD 528
#define BITS 145

int OnOff[BITS] =   {1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,0,1,0,0,0,1,1,1,0,1,1,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,0,1,1,1,0,1,0,0,0,   1,1,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,0,1,0,0,0,1,1,1,0,1,1,1,0,1,0,0,0,1,1,1,0,1,1,1,0,1,1,1,0,1,0,0,0,1,1,1,0,1,0,0,0,1,0,0,0};

int Red[BITS] =     {1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,0,1,0,0,0,1,1,1,0,1,1,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,0,1,1,1,0,1,0,0,0,   1,0,0,0,1,1,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,0,1,0,0,0,1,1,1,0,1,1,1,0,1,0,0,0,1,1,1,0,1,1,1,0,1,1,1,0,1,0,0,0,1,1,1,0,1,0,0,0};
int Green[BITS] =   {1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,0,1,0,0,0,1,1,1,0,1,1,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,0,1,1,1,0,1,0,0,0,   1,0,0,0,1,0,0,0,1,1,1,0,1,0,0,0,1,0,0,0,1,1,1,0,1,0,0,0,1,1,1,0,1,1,1,0,1,1,1,0,1,0,0,0,1,1,1,0,1,1,1,0,1,0,0,0,1,1,1,0,1,0,0,0};
int Blue[BITS] =    {1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,0,1,0,0,0,1,1,1,0,1,1,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,0,1,1,1,0,1,0,0,0,   1,1,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,0,1,1,1,0,1,0,0,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,0,0,0,1,0,0,0};
int White[BITS] =   {1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,0,1,0,0,0,1,1,1,0,1,1,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,0,1,1,1,0,1,0,0,0,   1,1,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,0,1,0,0,0,1,1,1,0,1,0,0,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,0,0,0,1,1,1,0,1,0,0,0};
int SpeedP[BITS] =  {1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,0,1,0,0,0,1,1,1,0,1,1,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,0,1,1,1,0,1,0,0,0,   1,0,0,0,1,0,0,0,1,1,1,0,1,0,0,0,1,1,1,0,1,0,0,0,1,0,0,0,1,1,1,0,1,1,1,0,1,1,1,0,1,0,0,0,1,1,1,0,1,0,0,0,1,1,1,0,1,1,1,0,1,0,0,0};
int SpeedM[BITS] =  {1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,0,1,0,0,0,1,1,1,0,1,1,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,0,1,1,1,0,1,0,0,0,   1,0,0,0,1,1,1,0,1,1,1,0,1,0,0,0,1,1,1,0,1,0,0,0,1,0,0,0,1,1,1,0,1,1,1,0,1,0,0,0,1,0,0,0,1,1,1,0,1,0,0,0,1,1,1,0,1,1,1,0,1,0,0,0};
int ModeP[BITS] =   {1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,0,1,0,0,0,1,1,1,0,1,1,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,0,1,1,1,0,1,0,0,0,   1,0,0,0,1,1,1,0,1,1,1,0,1,0,0,0,1,1,1,0,1,0,0,0,1,1,1,0,1,1,1,0,1,1,1,0,1,0,0,0,1,0,0,0,1,1,1,0,1,0,0,0,1,1,1,0,1,0,0,0,1,0,0,0};


void setup()
{
  pinMode(TX_PIN, OUTPUT);

  // This is just for debugging purposes  
  Serial.begin(115200);  
}

void send_command()
{
  Serial.println(&quot;Boom!\n&quot;);

  // the remote sends our signal at least twice. Sending 4 times seems to be the most reliable.
  for (int j = 0; j &amp;lt; 4; j++)
  {
		on_off();
  }
  // Here we make sure we are not transmitting anything.
  digitalWrite(TX_PIN, LOW);
}

void on_off()
{
	for (int i = 0; i &amp;lt; BITS-1; i++)
	{
	    if (OnOff[i] != 0) {
		digitalWrite(TX_PIN, HIGH);
            } else {
		digitalWrite(TX_PIN, LOW);
            }
	    delayMicroseconds(BIT_PERIOD);
	}
}

void loop() {
  send_command();
  delay(1000);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As you can see this sample code is very easy. I actually decoded all the buttons from my remote but I am sending only one with the test code. Also you can notice that the first 80 bits from our signal is a preamble and then it follows the specific command.
Also, this remote sends the message at least twice and I found out that sending it 4 times is even more reliable.&lt;/p&gt;

&lt;p&gt;Below you can see the fabricated message captured and analyzed and if you look carefully you can see there is a lot less ripple at the top of the signal. In effect we are actually sending a better signal.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/rf_remote_fabricated.png&quot; alt=&quot;Fabricated On/Off signal&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Now you can imagine that it would be possible to extend this so that I would create a smart remote which turns the LEDs certain colors for various notifications such as when Forex prices reach a certain value or when a Skype messages is received. In addition to that we could consolidate a bunch of these remotes into a single smarter remote that also adjusts heating, opens the garage door or whatever else you might find interesting.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Hacking this RF remote took a few hours and if we can do it, everybody from the neighborhood can do it. All the materials required could be bought for $15. NEVER use cheap wireless remotes for controlling things that you care about!&lt;/p&gt;

&lt;p&gt;IR remotes are way safer because they don’t transmit in the hood. The reverse engineering is similar but you need to be there physically.&lt;/p&gt;

&lt;h4 id=&quot;footnotes&quot;&gt;Footnotes:&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;If you stare at this even more you could also draw the conclusion that it could be PWM with two different duty cicles of either 25% or 75%. Nevertheless the OOK modulation could easily accomodate this scenario because we just send 4 bits instead of one with a different duty cycle.&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>MicroSD card quick test</title>
   <link href="/gadgets/2015/06/15/microsd-card-quick-test.html"/>
   <updated>2015-06-15T00:00:00+00:00</updated>
   <id>/gadgets/2015/06/15/microsd-card-quick-test</id>
   <content type="html">&lt;p&gt;MicroSD cards are everywhere these days but since these days it’s possible to film in UHD or in high speed with action cameras and phones it’s actually very important how quick these cards are at writing this data.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/microsd-cards.png&quot; alt=&quot;MicroSD card&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Of course these cards could also be used as storage for all those boards which run Linux, such as the well known Raspberry Pi but in this case a durability test would be just as important as a speed test.&lt;/p&gt;

&lt;h2 id=&quot;method&quot;&gt;Method&lt;/h2&gt;

&lt;p&gt;I took four of the MicroSD cards which I found in the house and which could be easily found in stores. I was only interested in the write speed to card so I used dd to dump data to the card.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dd if=/dev/zero of=/root/card/testfile bs=1M count=1024 oflag=direct&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The card was tested in the SD/MMC port on the laptop, with a fast card reader in USB 2.0 and in USB 3.0. The last option was significantly faster so I used the card reader in a USB 3.0 port for all the tests.&lt;/p&gt;

&lt;p&gt;The tests were run multiple times and the average was considered. It was proven that most cards have a very unpredictable performance. The minimum write speed can sometimes be half of the maximum speed.&lt;/p&gt;

&lt;h2 id=&quot;results&quot;&gt;Results&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Lexar 633x&lt;/th&gt;
      &lt;th&gt;Sony&lt;/th&gt;
      &lt;th&gt;Kingston Class 10&lt;/th&gt;
      &lt;th&gt;Kingston Class 4&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;40 MB/s&lt;/td&gt;
      &lt;td&gt;17 MB/s&lt;/td&gt;
      &lt;td&gt;9.5 MB/s&lt;/td&gt;
      &lt;td&gt;3.5 MB/s&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;One card can be at least 10 times slower than another so it’s quite possible to get a card which is not fast enough for filming. The industry has the &lt;a href=&quot;https://www.sdcard.org/consumers/speed/speed_class/&quot;&gt;UHS class 3&lt;/a&gt; marking, which defines the minimum writing speed of 30MB/s, but the indication is frequently misused. I recommend you get a card which was tested by someone and has proven to be good enough.&lt;/p&gt;

&lt;p&gt;The writing speed for the SD cards can also fluctuate quite badly so performing only one write test is not enough. Out of these 4 cards I tested, Lexar 633x was the only one which has consistent performance and it was the fastest one.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>PHP on Google App Engine</title>
   <link href="/cloud/2013/11/14/php-on-google-app-engine.html"/>
   <updated>2013-11-14T00:00:00+00:00</updated>
   <id>/cloud/2013/11/14/php-on-google-app-engine</id>
   <content type="html">&lt;p&gt;You can host your PHP apps on the Google infrastructure and only pay according to how popular your app is. Let’s see how it actually works.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bogdan.nimblex.net/assets/img/google-appengine-php.gif&quot; alt=&quot;PHP App Engine&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This sounds super nice, specially since it can even be free of charge for personal websites or provide automatic scalability for sites which plan to attract a lot of traffic.&lt;/p&gt;

&lt;h2 id=&quot;how-straightforward-is-that&quot;&gt;How straightforward is that?&lt;/h2&gt;

&lt;p&gt;Well, not very. To maintain very high level of scalability your code doesn’t use a LAMP stack like you’re used to, but instead it uses a container which has some advantages and some limitations.&lt;/p&gt;

&lt;h3 id=&quot;the-main-limitations&quot;&gt;The main limitations:&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Other computers can only connect to the application by making HTTP (or HTTPS) requests on the standard ports. The app container doesn’t even have a normal networking stack so it will communicate externally by doing &lt;a href=&quot;https://developers.google.com/appengine/docs/php/urlfetch/&quot;&gt;URL Fetch&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Applications cannot write to the file system. The app must use the App Engine datastore, memcache or other services for all data that persists between requests.&lt;/li&gt;
  &lt;li&gt;Application code only runs in response to a web request, a queued task, or a scheduled task, and must return response data within 60 seconds in any case. A request handler cannot spawn a sub-process or execute code after the response has been sent.&lt;/li&gt;
  &lt;li&gt;No way of using PHP modules which are not supported by Google App Engine.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;the-main-advantages&quot;&gt;The main advantages:&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;It’s very efficient as it utilizes the minimum amount of resources necessary to run your code, thus it can be very cost effective.&lt;/li&gt;
  &lt;li&gt;Having a minimal read-only environment where you don’t even have a shell makes things very secure both for your app and for Google.&lt;/li&gt;
  &lt;li&gt;Integration with other very nice services such as CloudSQL, PageSpeed and others.&lt;/li&gt;
  &lt;li&gt;Introduction of new “concepts” such as Task Queues which makes things more efficient.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;running-off-the-shelf-apps&quot;&gt;Running off the shelf apps:&lt;/h3&gt;

&lt;p&gt;If you are interested in running something complex app like Joomla, Wordpress or many others, App engine is probably not the way to go, even though PHP is &lt;a href=&quot;http://php-minishell.appspot.com/phpinfo&quot;&gt;almost standard&lt;/a&gt; and they could run.&lt;/p&gt;

&lt;p&gt;Specifically, these two are made such that you customize them with modules and templates from the admin panel by uploading and decompressing files on the file system, which is not possible here. Fortunately there is a workaround for that because you can do it in your local development environment and then redeploy the application. Actually, there is even a &lt;a href=&quot;https://developers.google.com/appengine/articles/wordpress&quot;&gt;tutorial&lt;/a&gt; made especially for WordPress.&lt;/p&gt;

&lt;p&gt;Also, all these have Media Managers for uploading photos and other files you offer for download on your site. For these you could have modifications done in the code or plugins which allow &lt;a href=&quot;https://developers.google.com/appengine/docs/php/googlestorage/#writing_to_google_cloud_storage&quot;&gt;uploading files&lt;/a&gt; to Google Cloud Storage.&lt;/p&gt;

&lt;h3 id=&quot;running-new-apps&quot;&gt;Running new apps:&lt;/h3&gt;

&lt;p&gt;If you plan to write a new app, indeed Google App Engine will almost constrain you from the beginning to make it scalable. With some of the limitations they provide you also get benefits, but certainly there are things to consider beyond that.&lt;/p&gt;

&lt;p&gt;For example, if your application will get more complex, then you’ll want to start using &lt;a href=&quot;https://developers.google.com/appengine/docs/php/taskqueue/&quot;&gt;Task Queues&lt;/a&gt;, not only because it’s a great concept but because you won’t have a choice. I bet Google uses this a lot with their apps to give the impression of everything happening instantly. Unfortunately, the downside is that using this creates vendor lockin and then you’ll be stuck with having to use App Engine forever.&lt;/p&gt;

&lt;h3 id=&quot;other-considerations&quot;&gt;Other considerations:&lt;/h3&gt;

&lt;p&gt;For MySQL, Google also has a separate service called Cloud SQL which is pretty nice. You connect to it using a socket connection and of course there are some decent limits in place. The Cloud SQL service should be fine for small to medium traffic levels where it’s not necessary to tune MySQL or to store lots of data.&lt;/p&gt;

&lt;p&gt;While running your local &lt;a href=&quot;https://developers.google.com/appengine/docs/php/tools/devserver&quot;&gt;development environment&lt;/a&gt; is the way to go in most situations, having to do that for simple tasks such as installing a theme to platforms such as Wordpress or Joomla is definitely not very convenient. I will have to do it on the computer where I have everything setup and it would be out of the reach for non-technical people.&lt;/p&gt;

&lt;p&gt;The Google Apps admin interface is not done yet. It switches back and forth between the old and new depending on the service you access and some of the things are not integrated well and clear. While running my test Wordpress app I qualify for free of charge usage on App Engine but I need to enable billing for using Cloud SQL and Cloud Storage. These also seem to be cost effective for low usage but I can’t really figure out how much I’d have to pay if I have an app that gets 100 requests per day.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion:&lt;/h2&gt;

&lt;p&gt;App Engine for PHP seems awesome if you develop specifically for it and if you are fine with going on purpose into vendor lock-in. For other situations also consider the alternatives (shared hosting, virtual machines, etc.).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Update 1 (18 Dec 2013):&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I figured out how much it costs to run the smallest setup for hosting WordPress. For the past month the cost was $15.25 in total from which the Google SQL D0 Service was ~$15. I didn’t make any requests to the site after testing it initially but CloudSQL charged me for ~75% of the hours because every few hours there were some read and write openration. Also, in the logs there are a few unknown errors associated with backups.&lt;/p&gt;
</content>
 </entry>
 
 
</feed>
