Ferdinand Keilhttps://ferdinandkeil.com/2022-05-05T16:30:00+02:00Minify JSON using PowerShell2022-05-05T16:30:00+02:002022-05-05T16:30:00+02:00ferdinandtag:ferdinandkeil.com,2022-05-05:/minify-json-using-powershell.html<p>PowerShell is Windows' powerful and built-in scripting language. And just as a Linux shell it comes with loads of useful commands <a class="footnote-reference" href="#footnote-1" id="footnote-reference-1">[1]</a>. Recently I wanted to minify some JSON code to check how much that would shrink its size. I got <a class="reference external" href="https://stackoverflow.com/questions/42082289/minify-json-with-powershell">some inspiration</a> from StackOverflow and finally came up with …</p><p>PowerShell is Windows' powerful and built-in scripting language. And just as a Linux shell it comes with loads of useful commands <a class="footnote-reference" href="#footnote-1" id="footnote-reference-1">[1]</a>. Recently I wanted to minify some JSON code to check how much that would shrink its size. I got <a class="reference external" href="https://stackoverflow.com/questions/42082289/minify-json-with-powershell">some inspiration</a> from StackOverflow and finally came up with the following snippet.</p>
<div class="highlight"><pre><span></span><span class="nb">Get-Content</span> <span class="n">yourfile</span><span class="p">.</span><span class="n">json</span> <span class="p">|</span> <span class="nb">ConvertFrom-Json</span> <span class="p">|</span> <span class="nb">ConvertTo-Json</span> <span class="n">-Compress</span> <span class="p">|</span> <span class="nb">Out-File</span> <span class="n">yourfile</span><span class="p">.</span><span class="n">min</span><span class="p">.</span><span class="n">json</span>
</pre></div>
<p>So let break down what's happening here. First, the contents of the file that is to be minified have to be read using <cite>Get-Content</cite>. This content is passed to <cite>ConvertFrom-Json</cite>, which returns a proper JSON object. The actual magic is done by <cite>ConvertTo-Json</cite>, which converts that object back to a string but also compresses it courtesy of the <cite>-Compress</cite> option. Finally, this string is written to a file again using <cite>Out-File</cite> <a class="footnote-reference" href="#footnote-2" id="footnote-reference-2">[2]</a>. And if that last part is omitted the string is printed to the terminal.</p>
<p>I deliberately chose to not use input/output redirection here, but it would work just as well. Obviously there are many other solutions to this problem. I just like this one, as it comes batteries-included on every recent Windows machine 😊.</p>
<table class="docutils footnote" frame="void" id="footnote-1" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#footnote-reference-1">[1]</a></td><td>Or <em>cmdlets</em>, as commands are called in PowerShell.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="footnote-2" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#footnote-reference-2">[2]</a></td><td>FYI, <cite>Out-File</cite> also has an encoding option that might come in handy.</td></tr>
</tbody>
</table>
Quickly Serve a Local Directory2022-01-29T18:00:00+01:002022-01-29T18:00:00+01:00ferdinandtag:ferdinandkeil.com,2022-01-29:/quickly-serve-a-local-directory.html<p>When working on HTML files some things won't work if they're just opened from the local hard-drive. The solution is to present them to your browser through some kind of webserver. Setting up a <em>proper</em> webserver like <a class="reference external" href="https://www.nginx.com/">nginx</a> or <a class="reference external" href="https://httpd.apache.org/">Apache</a> would be overkill here.</p>
<p>But if Python is available in …</p><p>When working on HTML files some things won't work if they're just opened from the local hard-drive. The solution is to present them to your browser through some kind of webserver. Setting up a <em>proper</em> webserver like <a class="reference external" href="https://www.nginx.com/">nginx</a> or <a class="reference external" href="https://httpd.apache.org/">Apache</a> would be overkill here.</p>
<p>But if Python is available in your environment, everything you need is already there 🤩. This command</p>
<div class="highlight"><pre><span></span>python3 -m http.server --bind <span class="m">127</span>.0.0.1 <span class="m">8000</span>
</pre></div>
<p>will serve the current directory on port <tt class="docutils literal">8000</tt>! Adding <tt class="docutils literal"><span class="pre">--bind</span> 127.0.0.1</tt> makes sure that the server is only available locally.</p>
<p>To wrap this up into a handy command called <tt class="docutils literal">serve</tt>, just add the following code to your <tt class="docutils literal">.bash_aliases</tt> <a class="footnote-reference" href="#footnote-1" id="footnote-reference-1">[*]</a>.</p>
<div class="highlight"><pre><span></span><span class="nb">alias</span> <span class="nv">serve</span><span class="o">=</span><span class="s1">'python3 -m http.server --bind 127.0.0.1 8000'</span>
</pre></div>
<table class="docutils footnote" frame="void" id="footnote-1" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#footnote-reference-1">[*]</a></td><td>If you're not using <tt class="docutils literal">bash</tt> I assume you know where to put this 😬.</td></tr>
</tbody>
</table>
Breaking up Exceptions2021-10-12T12:30:00+02:002021-10-12T12:30:00+02:00ferdinandtag:ferdinandkeil.com,2021-10-12:/breaking-up-exceptions.html<p>These days I stumbled upon a weird problem where a Python script of mine would <em>silently</em> fail to save some data to a file. Turns out you can suppress exceptions in a loop with <cite>break</cite> 😧.</p>
<p>Let me start by outlining what I was trying to achieve: I have a process …</p><p>These days I stumbled upon a weird problem where a Python script of mine would <em>silently</em> fail to save some data to a file. Turns out you can suppress exceptions in a loop with <cite>break</cite> 😧.</p>
<p>Let me start by outlining what I was trying to achieve: I have a process where data is received and the saved to a file. Sometimes the retrieval fails so I start it again for certain number of retries. The failure is signaled by a certain exception which in turn is caught using a <cite>try</cite> block. However, if an unexpected exception is raised it should break the process and propagate up.</p>
<p>This is a minimal example of the code that was <em>supposed</em> to do this:</p>
<div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">NoSurprise</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
<span class="k">pass</span>
<span class="n">retries</span> <span class="o">=</span> <span class="mi">3</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">retries</span><span class="p">):</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">raise</span> <span class="n">NoSurprise</span> <span class="c1"># <- well that's no surprise</span>
<span class="k">except</span> <span class="n">NoSurprise</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'try again'</span><span class="p">)</span>
<span class="k">pass</span>
<span class="k">finally</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'done'</span><span class="p">)</span>
<span class="k">break</span>
</pre></div>
<p>If the expected exception <cite>NoSurprise</cite> is caught the loop will try again and up to three times. Running the code we get the output <cite>try again</cite> three times which is the desired behavior.</p>
<p>Now let's try again with an <em>unexpected</em> exception.</p>
<div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">retries</span><span class="p">):</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">Exception</span> <span class="c1"># <- this we don't expect</span>
<span class="k">except</span> <span class="n">NoSurprise</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'try again'</span><span class="p">)</span>
<span class="k">pass</span>
<span class="k">finally</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'done'</span><span class="p">)</span>
<span class="k">break</span>
</pre></div>
<p>Running this just outputs <cite>done</cite>. Well, that's no good!</p>
<p>Let's go over what happens here. The exception is raised, but it doesn't fit the <cite>except</cite> statement, so it is skipped The <cite>finally</cite> block is run always, regardless what happened earlier. So it will happily print <cite>done</cite> and then break the loop. But what happened to the exception? Well, once the loop is broken the exception is gone and the rest of the code runs happily.</p>
<p>This is the fix for this code snippet.</p>
<div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">retries</span><span class="p">):</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">Exception</span> <span class="c1"># <- this we don't expect</span>
<span class="k">except</span> <span class="n">NoSurprise</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'try again'</span><span class="p">)</span>
<span class="k">pass</span>
<span class="k">else</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'done'</span><span class="p">)</span>
<span class="k">break</span>
</pre></div>
<p>All I did was replace <cite>finally</cite> with <cite>else</cite>. What's the difference, I hear you ask. As I wrote earlier, the <cite>finally</cite> block will get executed no matter what. The <cite>else</cite> block on the other hand will only be executed if no exception was raised in the <cite>try</cite> block <a class="footnote-reference" href="#footnote-1" id="footnote-reference-1">[1]</a>. Running this piece of code Python informs us that an exception was raised an prints a traceback, which is what I wanted in the first place ☺️.</p>
<p>Python has very powerful constructs, but as they say ...</p>
<img alt="" src="https://ferdinandkeil.com/uploads/2021/10/uncleben.jpg" style="width: 300px;" />
<table class="docutils footnote" frame="void" id="footnote-1" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#footnote-reference-1">[1]</a></td><td>For a authoritative source please refer to the Python docs: <a class="reference external" href="https://docs.python.org/3/tutorial/errors.html#defining-clean-up-actions">https://docs.python.org/3/tutorial/errors.html#defining-clean-up-actions</a></td></tr>
</tbody>
</table>
Accelerated Testing Tip #2: Build an Automatic Water Supply2021-05-15T16:00:00+02:002021-05-15T16:00:00+02:00ferdinandtag:ferdinandkeil.com,2021-05-15:/accelerated-testing-tip2-automatic-water-supply.html<p>Running accelerated tests at elevated humidity levels in a climate chamber requires a (constant) supply of deionized water to feed the humidifier. Sealing the chamber goes a long way to minimize the loss of water during the test, however the setup will never be vapor-tight. The water supply needs to …</p><p>Running accelerated tests at elevated humidity levels in a climate chamber requires a (constant) supply of deionized water to feed the humidifier. Sealing the chamber goes a long way to minimize the loss of water during the test, however the setup will never be vapor-tight. The water supply needs to be adequate to replenish the water lost to the outside of the chamber. Most climate chambers come with an integrated water tank and that might be all that is necessary for short test runs. However, once the tests start to last for weeks or even months, an external tank is a worthwhile addition to the test setup. To quote the <a class="reference external" href="https://espec.com/na/chamber_faq/answer/humidity_water/">ESPEC North-America homepage</a>:</p>
<blockquote>
Be sure the water tank can be filled easily because you will be doing this on a regular basis (once a week to once a month).</blockquote>
<p>Obviously, the tank needs refilling less frequently if it is bigger (duh 😑). In the following I will list the requirements for using an external water tank, the equipment necessary for connecting it to the chamber and some general advice for installing the system.</p>
<div class="section" id="system-overview">
<h2>System Overview</h2>
<p><object data="https://ferdinandkeil.com/uploads/2021/05/water_supply_overview.svg" type="image/svg+xml">water_supply_overview</object></p>
<p>Water tanks alone won't do you much good, as the external water supply inlet of the climate chambers need a defined water pressure to work properly. At least mine do. The picture above shows the setup I came up with. Two tanks of 60 l each sit on a wooden shelf. Both feed into a pump used to pressurize the water, which is then distributed to the climate chambers. To prevent potential damage the pump has its own control circuit in an electric cabinet.</p>
</div>
<div class="section" id="pump-control-circuit">
<h2>Pump & Control Circuit</h2>
<div class="figure">
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2021/05/water_supply_control.jpg"><img alt="" src="https://ferdinandkeil.com/uploads/2021/05/thumbnails/450x_/water_supply_control.jpg" /></a>
<p class="caption">Board with pump and control circuit.</p>
</div>
<p>The picture above shows the pump and distribution pipework together with the control circuit. The pump is a <a class="reference external" href="https://www.lilie.com/produkte/wassertuning/pumpen/pumpen-fuer-caravaning/classicserie/">model made for caravaning</a> and features an integrated pressure switch. The pump only turns on when the pressure is below a certain threshold. It runs until the configured pressure is reached and then turns off. It is accompanied by a water filter to the left and a <a class="reference external" href="https://www.obelink.de/fiamma-a20-akkumulatorentank.html">pressure storage tank</a> to the right. The pump has to run less frequently if a storage tank is added, thus reducing the wear.</p>
<p>Below the pump is a y-piece distributing the water to both climate chambers. Each connection gets its own shut-off valve, which is useful when servicing the system. And a pressure gauge, <strong>which is an absolute must</strong>! You will want to check the water pressure sooner or later, so don't skimp on the pressure gauge <a class="footnote-reference" href="#footnote-1" id="footnote-reference-1">[1]</a>.</p>
<p>The good thing about the pump is it is self-regulating. So as long as it is properly set up you don't have to worry about the water pressure. However, it has one weakness as it does not like to run dry. If it can't pump any water it can't increase the pressure and will run until it's dead. This is what the control circuit in the small electric cabinet is for. A float switch in one of the tanks monitors the water level. If it sinks below the threshold the pump is turned off by a relay and the warning light is activated. A timer-relay is connected between the float switch and the rest of the circuit to debounce the signal. This prevents the relays from switching repeatedly when the switch gets bumped, e.g. when water is refilled.</p>
<div class="figure">
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2021/05/float_switch.jpg"><img alt="" src="https://ferdinandkeil.com/uploads/2021/05/thumbnails/450x_/float_switch.jpg" /></a>
<p class="caption">Float switch mounted at the end of a piece of PVC pipe.</p>
</div>
<p>The float switch is mounted at the end of a piece of PVC pipe so that it reaches down to the critical water level. Its cable runs inside of the watertight pipe. It gets screwed into the top of the tank with a 3D-printed cap.</p>
</div>
<div class="section" id="results">
<h2>Results</h2>
<p>This system has been running reliably for months without a hitch. Having large storage tanks definitely reduces the workload when running long-term tests. Mounting the pump and accompanying components on a piece of plywood makes it easy to modify or extend the system later on.</p>
<p>The fittings used are plastic or brass. So far they don't show any wear. Stainless steel fittings would have been even better, given that the deionized water running through the system is quite aggressive. Unfortunately, they are also quite expensive 😔.</p>
<table class="docutils footnote" frame="void" id="footnote-1" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#footnote-reference-1">[1]</a></td><td>Like I did at first. I then had to add it later, as it is the best way to check whether the system is working properly.</td></tr>
</tbody>
</table>
</div>
A simple screen capture tool for the Rigol DS1054Z in pure bash2020-12-04T19:00:00+01:002020-12-04T19:00:00+01:00ferdinandtag:ferdinandkeil.com,2020-12-04:/screen-capture-rigol-ds1054z-bash.html<p>When working on a project, I sometimes want to get a quick screen capture from my Rigol DS1054Z for documentation purposes. In the past I have used <a class="reference external" href="https://www.teuniz.net/DSRemote/">DSRemote</a> for this. However, being a tool to remotely control your scope it doesn't cope well with using the physical inputs on the …</p><p>When working on a project, I sometimes want to get a quick screen capture from my Rigol DS1054Z for documentation purposes. In the past I have used <a class="reference external" href="https://www.teuniz.net/DSRemote/">DSRemote</a> for this. However, being a tool to remotely control your scope it doesn't cope well with using the physical inputs on the scope at the same time. What I needed was a simple tool to just get a screenshot from the scope, nothing more. I also didn't want to install any requirements. Luckily, Linux comes with a USB-TMC (test and measurement class) driver built-in. I then went along trying to figure out the simplest way to get a screen capture using pure bash. The result is shown below.</p>
<div class="highlight"><pre><span></span><span class="ch">#!/bin/bash</span>
<span class="o">(</span>
<span class="nb">echo</span> <span class="s1">':DISPlay:DATA? ON,OFF,PNG'</span><span class="p">;</span>
head -c <span class="k">$(</span>head -c <span class="k">$(</span>head -c <span class="m">2</span> <span class="p">|</span> tail -c <span class="m">1</span><span class="k">)</span> <span class="p">|</span> sed <span class="s1">'s/^0*//'</span><span class="k">)</span> > capture.png
<span class="o">)</span> <span class="m">3</span><>/dev/usbtmc1 <<span class="p">&</span><span class="m">3</span> ><span class="p">&</span><span class="m">3</span>
</pre></div>
<p>This assumes the scope shows up as <cite>/dev/usbtmc1</cite> and you want the screen capture written to <cite>capture.png</cite>.</p>
<p>What does it do? Well, it starts by opening the device <cite>/dev/usbtmc1</cite> (conveniently generated by the kernel when plugging in the scope) for reading an writing. The <cite>stdin</cite> and <cite>stdout</cite> of the block in parentheses are then connected to the device. Now for the actual magic: first, a screen capture in PNG format is requested using the appropriate SCPI commands, by echo'ing them to the scope. The scopes reply looks like this <cite>#9001152054...</cite>, where <cite>...</cite> represents the actual binary image data. The hash sign (<cite>#</cite>) is always there and can simply be ignored. The next character is a number indicating the length of the header string. In the bash script this is separated using a combination of <cite>head</cite> and <cite>tail</cite>. Using this length, the remaining header is retrieved. This part contains the size of the image in bytes. The leading zeroes are removed using <cite>sed</cite> and then <cite>head</cite> is used to retrieve the image data itself, which is finally piped to the output file <cite>capture.png</cite>.</p>
<p>And there you have it, a simple screen capture tool for Rigol scopes in just four lines of bash code!</p>
Getting a nice, high-resolution terminal on Linux with an NVIDIA GPU and EFI2020-05-26T16:00:00+02:002020-05-26T16:00:00+02:00ferdinandtag:ferdinandkeil.com,2020-05-26:/high-resolution-terminal-linux-nvidia-efi.html<p>I finally replaced my more than ten year old 24" Dell monitor with a Samsung 49" curved display. Splitting it in three parts (1:2:1) makes for a very ergonomic desktop, as one's turning the head equally to both sides.</p>
<p>However, the unusually high resolution of the display (5120x1440 …</p><p>I finally replaced my more than ten year old 24" Dell monitor with a Samsung 49" curved display. Splitting it in three parts (1:2:1) makes for a very ergonomic desktop, as one's turning the head equally to both sides.</p>
<p>However, the unusually high resolution of the display (5120x1440 pixels) causes its own set of problems. The toughest one so far was setting a higher resolution during boot and in terminals (1280x1024 just isn't cutting it). Linux can do it, GRUB has a setting for it, EFI shouldn't be a problem and the NVIDIA driver supports it as well. So I kept changing options in <cite>/etc/default/grub</cite> for hours, even breaking GRUB in the process.</p>
<p>Turns out, it has nothing to do with the GRUB config. <a class="reference external" href="https://forum.manjaro.org/t/how-to-get-high-resolution-grub-console-on-nvidia-gpus-in-uefi/124855">This post in the Manjaro forum</a> got me on the right track: mainboards with EFI firmware have a so called <abbr title="Compatibility Support Module">CSM</abbr> to support legacy OSes. If it is enabled, the NVIDIA driver limits the framebuffer resolution (that is used for the terminal) to 1280x1024 pixels. So one has to <strong>disable CSM</strong> for the NVIDIA driver to output higher resolutions in terminals. Now that I have disabled the CSM, everything is working brilliantly without any additional settings in the GRUB config.</p>
Where is the On-Off Switch on the Logitech ERGO K860 Keyboard?2020-05-17T16:20:00+02:002020-05-17T16:20:00+02:00ferdinandtag:ferdinandkeil.com,2020-05-17:/logitech-k860-switch.html<p>The <a class="reference external" href="https://www.logitech.com/product/k860-split-ergonomic-keyboard">Logitech ERGO K860</a> is a really nice ergonomic keyboard. I got one recently to make typing less harsh on my wrists. One very nice feature is that the keyboard can control up to three devices. There are even dedicated buttons to switch between them!</p>
<p>Before you can use the …</p><p>The <a class="reference external" href="https://www.logitech.com/product/k860-split-ergonomic-keyboard">Logitech ERGO K860</a> is a really nice ergonomic keyboard. I got one recently to make typing less harsh on my wrists. One very nice feature is that the keyboard can control up to three devices. There are even dedicated buttons to switch between them!</p>
<p>Before you can use the keyboard with a device you need to pair it with the Unifying Receiver in that device. This involves turning the keyboard off and on again. If you - like me - struggle to find the switch, here it is.</p>
<div class="figure">
<img alt="" src="https://ferdinandkeil.com/uploads/2020/05/logitech-k860-switch.jpg" />
<p class="caption">Smack in the middle it is, right under the <em>logi</em> logo.</p>
</div>
Tab Completion in Bash for recent Conda Versions2020-04-09T15:00:00+02:002020-04-09T15:00:00+02:00ferdinandtag:ferdinandkeil.com,2020-04-09:/tab-completion-conda.html<p>Unfortunately, the tab completion support included in <tt class="docutils literal">conda</tt> has been <a class="reference external" href="https://docs.conda.io/projects/conda/en/latest/user-guide/configuration/enable-tab-completion.html">deprecated with version 4.4</a>. On Github <a class="reference external" href="https://github.com/tartansandal/conda-bash-completion">tartansandal</a> has been working on a new completion facility. Installing it is trivial:</p>
<div class="highlight"><pre><span></span>conda install -c tartansandal conda-bash-completion
</pre></div>
<p>Found in <a class="reference external" href="https://github.com/conda/conda/issues/9178#issuecomment-552297636">Issue #9178 - Conda tab completion</a>.</p>
Enabling the Watchdog on a Raspberry Pi2020-04-06T12:00:00+02:002020-04-06T12:00:00+02:00ferdinandtag:ferdinandkeil.com,2020-04-06:/enabling-rpi-watchdog.html<p>To increase the reliability of embedded systems - especially ones that are hard to physically access - one can use an embedded watchdog. The watchdog, once activated, will reset the system if it is not fed for a certain time-interval. This guarantees a clean reset in case the system ends up in …</p><p>To increase the reliability of embedded systems - especially ones that are hard to physically access - one can use an embedded watchdog. The watchdog, once activated, will reset the system if it is not fed for a certain time-interval. This guarantees a clean reset in case the system ends up in an unresponsive state.</p>
<p>Luckily, the Raspberry Pi comes with a watchdog unit and with recent versions of Raspbian it is easier than ever to enable it:</p>
<div class="highlight"><pre><span></span><span class="nb">echo</span> <span class="s2">"RuntimeWatchdogSec=10s"</span> <span class="p">|</span> sudo tee -a /etc/systemd/system.conf
</pre></div>
<p>I am note sure if rebooting is necessary afterwards, but it certainly doesn't hurt. The <tt class="docutils literal">watchdog</tt> module is already included in the kernel and <a class="reference external" href="http://0pointer.de/blog/projects/watchdog">systemd</a> will take care of feeding it.</p>
<p>A <a class="reference external" href="https://www.cyberciti.biz/faq/understanding-bash-fork-bomb/">bash fork bomb</a> can be used to test it. The system should reset and reboot a few seconds after the command was executed.</p>
<div class="highlight"><pre><span></span>:<span class="o">(){</span> :<span class="p">|</span>:<span class="p">&</span> <span class="o">}</span><span class="p">;</span>: <span class="c1"># bash fork 💣</span>
</pre></div>
Network Booting a Raspberry Pi 4 from a CentOS 7 Machine2020-04-04T16:00:00+02:002020-04-04T16:00:00+02:00ferdinandtag:ferdinandkeil.com,2020-04-04:/network-booting-rpi4-from-centos7.html<p>First of all let, me state that the following instructions are specific for the Raspberry Pi 4 and a machine running CentOS 7. The instructions are based on two articles by <a class="reference external" href="https://hackaday.com/author/jonathanbennett492054495/">Jonathan Bennett</a> published on <a class="reference external" href="https://hackaday.com/">Hackaday</a>: <a class="reference external" href="https://hackaday.com/2018/10/08/hack-my-house-running-raspberry-pi-without-an-sd-card/">Hack My House: Running Raspberry Pi Without An SD Card</a> and <a class="reference external" href="https://hackaday.com/2019/11/11/network-booting-the-pi-4/">Network Booting The …</a></p><p>First of all let, me state that the following instructions are specific for the Raspberry Pi 4 and a machine running CentOS 7. The instructions are based on two articles by <a class="reference external" href="https://hackaday.com/author/jonathanbennett492054495/">Jonathan Bennett</a> published on <a class="reference external" href="https://hackaday.com/">Hackaday</a>: <a class="reference external" href="https://hackaday.com/2018/10/08/hack-my-house-running-raspberry-pi-without-an-sd-card/">Hack My House: Running Raspberry Pi Without An SD Card</a> and <a class="reference external" href="https://hackaday.com/2019/11/11/network-booting-the-pi-4/">Network Booting The Pi 4</a>. In addition to what Jonathan wrote in the articles, I also found several comments below them very helpful.</p>
<p>The CentOS specific parts of the instructions deal with its firewall and the required SELinux settings. These might not be needed for other distros, but are absolutely essential for CentOS.</p>
<img alt="" src="https://ferdinandkeil.com/uploads/2020/03/thumbnails/400x_/notsure_selinux_meme.jpg" />
<p><strong>Step 0: Prerequisites</strong></p>
<p>I will use this setup in a long-term experiment where a CentOS machine is controlling all the test-gear, including the Raspberry Pis. To separate the test-gear from the general network this machine is equipped with two network interfaces, where one (namely <tt class="docutils literal">enp0s3</tt>) is used exclusively to talk to an internal network connecting to the test-gear. This network uses the <tt class="docutils literal">10.0.0.0/24</tt> IP address range, with the CentOS machine being at <tt class="docutils literal">10.0.0.1</tt>. It will be added to the zone <tt class="docutils literal">internal</tt> in the <a class="reference external" href="https://firewalld.org/">firewall</a>. The figure below illustrates this setup.</p>
<div class="figure">
<img alt="" src="https://ferdinandkeil.com/uploads/2020/03/thumbnails/750x_/network-boot-rpi4-centos.png" />
<p class="caption">The network setup this guide is assuming. Note that the CentOS machine has two network interfaces.</p>
</div>
<p><strong>Step 1: Bootloader Settings</strong></p>
<p>The Raspberry Pi 4 has an on-board I2C boot EEPROM to store the boodloader and its settings. At the time of writing this, all Pis get shipped with a bootloader missing the PXE boot support. So the first step is to download, configure and install a beta version of the bootloader. The following commands are taken literally from Jonathan's article, the only change being the use of a more recent beta version. To run them on the Raspberry Pi you need a recent version of Raspbian or Raspbian Lite installed to an SD-card.</p>
<div class="highlight"><pre><span></span>sudo apt-get update
sudo apt-get upgrade
wget https://github.com/raspberrypi/rpi-eeprom/raw/master/firmware/stable/pieeprom-2020-01-17.bin
rpi-eeprom-config pieeprom-2020-01-17.bin.bin > bootconf.txt
sed -i s/0x1/0x21/g bootconf.txt
rpi-eeprom-config --out pieeprom-2020-01-17.bin-netboot.bin --config bootconf.txt pieeprom-2020-01-17.bin.bin
sudo rpi-eeprom-update -d -f ./pieeprom-2020-01-17.bin-netboot.bin
cat /proc/cpuinfo
ip addr
</pre></div>
<p>The last two commands returns general information about the Pi, including its serial number and MAC address. These will be needed later and you should write them down.</p>
<p>If you plan on network booting multiple Pis you can now use this SD-card and just need to run the last two lines (flash the reconfigured bootloader and retrieve information).</p>
<p><strong>Step 2: Preparing the NFS, DHCP and TFTP Servers</strong></p>
<p>On the CentOS machine start by installing the packages for the NFS and DHCP server, namely <tt class="docutils literal"><span class="pre">nfs-utils</span></tt> and <tt class="docutils literal">dnsmasq</tt>. You will also need a directory structure for both services. In accordance with the <a class="reference external" href="https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard">Filesystem Hierarchy Standard</a> put these in the <tt class="docutils literal"><span class="pre">/srv/tftp``and</span> <span class="pre">``/srv/nfs</span></tt> directories.</p>
<div class="highlight"><pre><span></span>sudo yum -y install nfs-utils dnsmasq
sudo mkdir -p /srv/nfs/rpi4-3a205fc0
sudo mkdir -p /srv/tftp/3a205fc0
sudo chmod <span class="m">777</span> /srv/tftp
</pre></div>
<p><strong>Step 3: Preparing the Boot Image</strong></p>
<p>Next you will need to prepare image the Raspberry Pi will boot. Start by downloading the latest version of Raspbian from the <a class="reference external" href="https://www.raspberrypi.org">Raspberry Pi homepage</a>. I use Raspbian Lite as the machine will run headless. Using the awesome <tt class="docutils literal">kpartx</tt> tool you can mount the root and boot partitions contained in the image and copy their contents to the appropriate directories in the NFS server root. I named the directory based on the serial number of my Raspberry Pi.</p>
<div class="highlight"><pre><span></span>mkdir bootmnt
mkdir rootmnt
wget -O raspbian_lite_latest.zip https://downloads.raspberrypi.org/raspbian_lite_latest
unzip raspbian_lite_latest.zip
sudo kpartx -a -v *.img <span class="c1"># this will produce unpredictable behavior if there are multiple .img files!</span>
sudo mount /dev/mapper/loop0p1 bootmnt/
sudo mount /dev/mapper/loop0p2 rootmnt/
sudo cp -a rootmnt/* /srv/nfs/rpi4-3a205fc0/
sudo cp -a bootmnt/* /srv/nfs/rpi4-3a205fc0/boot/
</pre></div>
<p>For PXE-boot support, two files in the <tt class="docutils literal">boot</tt> directory need to be updated as well.</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span> /srv/nfs/rpi4-3a205fc0/boot/
sudo rm start4.elf
sudo rm fixup4.dat
sudo wget https://github.com/Hexxeh/rpi-firmware/raw/stable/start4.elf
sudo wget https://github.com/Hexxeh/rpi-firmware/raw/stable/fixup4.dat
</pre></div>
<p>The boot settings for the Raspberry Pi need to be changed as well. First, the SSH server is enabled. Then the <tt class="docutils literal">fstab</tt> is cleaned so that it does not interfere with booting from the NFS share. Finally, tell the Pi to boot over the network by changing its <tt class="docutils literal">cmdline.txt</tt>.</p>
<div class="highlight"><pre><span></span>sudo touch /srv/nfs/rpi4-3a205fc0/boot/ssh
sudo sed -i /UUID/d /srv/nfs/rpi4-3a205fc0/etc/fstab
<span class="nb">echo</span> <span class="s2">"console=serial0,115200 console=tty root=/dev/nfs nfsroot=10.0.0.1:/srv/nfs/rpi4-3a205fc0,vers=4.1,proto=tcp rw ip=dhcp rootwait elevator=deadline"</span> <span class="p">|</span> sudo tee /srv/nfs/rpi4-3a205fc0/boot/cmdline.txt
</pre></div>
<p><strong>Step 4: Firewall Settings</strong></p>
<p>Before you continue with setting up the services, the firewall needs to be configured to make them available. As mentioned before I use a separate network interface to connect to the Pi. This interface is assigned to the <tt class="docutils literal">internal</tt> zone of the firewall. Then all the required services will be enabled for this zone. To apply the settings, the firewall needs to be reloaded.</p>
<div class="highlight"><pre><span></span>sudo firewall-cmd --permanent --zone internal --change-interface enp0s3
sudo firewall-cmd --permanent --zone internal --add-service nfs3
sudo firewall-cmd --permanent --zone internal --add-service mountd
sudo firewall-cmd --permanent --zone internal --add-service rpc-bind
sudo firewall-cmd --permanent --zone internal --add-service tftp
sudo firewall-cmd --permanent --zone internal --add-service dhcp
sudo firewall-cmd --permanent --zone internal --add-service dns
sudo firewall-cmd --reload
</pre></div>
<p><em>Note:</em> The DNS service is necessary if you plan on assigning a hostname to the Pi via DHCP (see last step). Otherwise the Pi will not be able to lookup its own IP via DNS.</p>
<p><strong>Step 5: Configuring the Services</strong></p>
<p>Now comes the configuration for the two services. Before you continue, use a bind-mount to make the Pi's <tt class="docutils literal">boot</tt> directory available to the TFTP server.</p>
<div class="highlight"><pre><span></span><span class="nb">echo</span> <span class="s2">"/srv/nfs/rpi4-3a205fc0/boot /srv/tftp/3a205fc0 none defaults,bind 0 0"</span> <span class="p">|</span> sudo tee -a /etc/fstab
sudo mount /srv/tftp/3a205fc0/
</pre></div>
<p>The files are now in the root directory of the TFTP server. However, it will not be able to access them as SELinux will prevent this. You therefore need to add a rule so that files in the <tt class="docutils literal">/srv/tftp</tt> directory get labelled correctly as files to be served via TFTP. After the rule is added it needs to be applied to the files already present.</p>
<div class="highlight"><pre><span></span>sudo semanage fcontext -a -t tftpdir_rw_t <span class="s2">"/srv/tftp(/.*)?"</span>
sudo restorecon -R /srv/tftp
</pre></div>
<p>The following commands make the necessary changes to the config files of both the NFS server and <tt class="docutils literal">dnsmasq</tt>. Here <tt class="docutils literal">dnsmasq</tt> will provide a DHCP service (with IPs in the range of <tt class="docutils literal">10.0.0.100</tt> to <tt class="docutils literal">10.0.0.200</tt>) and the TFTP server.</p>
<div class="highlight"><pre><span></span><span class="nb">echo</span> <span class="s2">"/srv/nfs/rpi4-3a205fc0 *(rw,sync,no_subtree_check,no_root_squash)"</span> <span class="p">|</span> sudo tee -a /etc/exports
<span class="nb">echo</span> <span class="s2">"interface=enp0s3"</span> <span class="p">|</span> sudo tee -a /etc/dnsmasq.d/pxe-boot
<span class="nb">echo</span> <span class="s2">"dhcp-range=10.0.0.100,10.0.0.200,12h"</span> <span class="p">|</span> sudo tee -a /etc/dnsmasq.d/pxe-boot
<span class="nb">echo</span> <span class="s2">"log-dhcp"</span> <span class="p">|</span> sudo tee -a /etc/dnsmasq.d/pxe-boot
<span class="nb">echo</span> <span class="s2">"enable-tftp"</span> <span class="p">|</span> sudo tee -a /etc/dnsmasq.d/pxe-boot
<span class="nb">echo</span> <span class="s2">"tftp-root=/srv/tftp"</span> <span class="p">|</span> sudo tee -a /etc/dnsmasq.d/pxe-boot
<span class="nb">echo</span> <span class="s1">'pxe-service=0,"Raspberry Pi Boot"'</span> <span class="p">|</span> sudo tee -a /etc/dnsmasq.d/pxe-boot
</pre></div>
<p>All that is left to do is enabling and starting the services.</p>
<div class="highlight"><pre><span></span>sudo systemctl <span class="nb">enable</span> dnsmasq
sudo systemctl <span class="nb">enable</span> rpcbind
sudo systemctl <span class="nb">enable</span> nfs-server
sudo killall dnsmasq <span class="c1"># see comment</span>
sudo systemctl <span class="nb">enable</span> dnsmasq
sudo systemctl <span class="nb">enable</span> rpcbind
sudo systemctl <span class="nb">enable</span> nfs-server
</pre></div>
<p><em>Note:</em> When trying to start <tt class="docutils literal">dnsmasq</tt> I would get an error hinting that there already was an instance of it running in the background. Using <tt class="docutils literal">killall</tt> this instance gets terminated and then <tt class="docutils literal">dnsmasq</tt> is started again.</p>
<p><strong>Step 6: Finishing Touches</strong></p>
<p>Power up the Pi and connect to it over SSH after it is booted. If the Pi does not answer, look in <tt class="docutils literal">/var/log/messages</tt> for <tt class="docutils literal">dnsmasq</tt>'s output.</p>
<p>My setup is supposed to be more permanent, so I want to assign a fixed IP to the Pi. This can be done with <tt class="docutils literal">dnsmasq</tt> as well.</p>
<div class="highlight"><pre><span></span><span class="nb">echo</span> <span class="s2">"dhcp-host=dc:a6:32:35:2d:06,rpi4-3a205fc0,10.0.0.31,infinite"</span> <span class="p">|</span> sudo tee -a /etc/dnsmasq.d/static-IPs
sudo systemctl restart dnsmasq
</pre></div>
<p>Now the Pi gets assigned the static IP <tt class="docutils literal">10.0.0.31</tt> based on its MAC address, which we retrieved in the first step. In continuing the naming scheme, it also gets assigned the hostname <tt class="docutils literal"><span class="pre">rpi4-3a205fc0</span></tt> based on its serial number. Before the Raspberry Pi will replace its default hostname <tt class="docutils literal">raspberrypi</tt> with the one assigned via DHCP, you need to reset it to <tt class="docutils literal">localhost</tt> (therefore, the following command needs to be run on the Pi).</p>
<div class="highlight"><pre><span></span>sudo hostnamectl set-hostname localhost
</pre></div>
<p>After rebooting the Pi and logging in once more the prompt should greet you with the freshly assigned hostname.</p>
<p><em>Note:</em> These last steps are especially useful when booting several Pis over the network, as each can be assigned a unique name.</p>
Missing Kernel Header when installing VBox-Guest Extensions on CentOS2020-03-22T15:00:00+01:002020-03-22T15:00:00+01:00ferdinandtag:ferdinandkeil.com,2020-03-22:/centos-missing-kernel-headers.html<p>When installing the <a class="reference external" href="https://www.virtualbox.org/">VirtualBox</a> guest-extensions on a fresh CentOS installation the installer asks for the kernel headers to compile the necessary modules. To install these just type:</p>
<div class="highlight"><pre><span></span>yum install kernel-devel kernel-headers
</pre></div>
<p>Here is the important part: when the installer for the guest-extensions keeps complaining that <tt class="docutils literal">The headers for the current …</tt></p><p>When installing the <a class="reference external" href="https://www.virtualbox.org/">VirtualBox</a> guest-extensions on a fresh CentOS installation the installer asks for the kernel headers to compile the necessary modules. To install these just type:</p>
<div class="highlight"><pre><span></span>yum install kernel-devel kernel-headers
</pre></div>
<p>Here is the important part: when the installer for the guest-extensions keeps complaining that <tt class="docutils literal">The headers for the current running kernel were not found</tt> you need to <strong>update your CentOS system first</strong>!</p>
<div class="highlight"><pre><span></span>yum update <span class="c1"># updates the complete system</span>
</pre></div>
<p>What happened here? The kernel headers from the repository are newer than the currently installed kernel (remember, fresh install). So either you install the kernel headers version specific for that kernel (<em>not recommended</em>) or you just update the kernel to the most recent version.</p>
Enable Audio Redirection for RDP on Windows 102020-03-21T16:00:00+01:002020-03-21T16:00:00+01:00ferdinandtag:ferdinandkeil.com,2020-03-21:/windows10-audio-redirection-rdp.html<p>When working at home I connect my work laptop to my router and then use my desktop as a terminal over <a class="reference external" href="https://en.wikipedia.org/wiki/Remote_Desktop_Protocol">RDP</a>. On my desktop (currently running <a class="reference external" href="http://releases.ubuntu.com/18.04.4/">Ubuntu 18.04</a>) I use the <tt class="docutils literal">xfreerdp</tt> command-line tool from the <a class="reference external" href="http://www.freerdp.com/">FreeRDP-project</a> and this setup has been working quite well for a while …</p><p>When working at home I connect my work laptop to my router and then use my desktop as a terminal over <a class="reference external" href="https://en.wikipedia.org/wiki/Remote_Desktop_Protocol">RDP</a>. On my desktop (currently running <a class="reference external" href="http://releases.ubuntu.com/18.04.4/">Ubuntu 18.04</a>) I use the <tt class="docutils literal">xfreerdp</tt> command-line tool from the <a class="reference external" href="http://www.freerdp.com/">FreeRDP-project</a> and this setup has been working quite well for a while.</p>
<p>However, due the <tt class="docutils literal">#coronavirus</tt> situation all meetings these days get replaced with calls. And as these are not phone calls, but work over some kind of website or desktop tool, it is very desireable for me to be able to connect my headset to my desktop and keep working over RDP as before. Enter <strong>audio redirection</strong>. This allows the RDP-host (aka the laptop) to access the client's audio inputs (e.g. microphone) and outputs (e.g. headphones).</p>
<p>The important <tt class="docutils literal">xfreerdp</tt> command-line options are <tt class="docutils literal">/sound</tt> and <tt class="docutils literal">/microphone:sys:alsa</tt> (it defaults to Pulse Audio, but this did not work for me). The remote audio device now shows up in Windows once connected over RDP. Frustratingly however, there was no sound when playing audio on the host. Turns out, you first have to enable the audio redirection in the host's <strong>Group Policies</strong>!</p>
<p>To do that open the <em>Local Group Policy Editor</em> by typing <tt class="docutils literal">gpedit.msc</tt> into the Windows search bar. Then navigate to <tt class="docutils literal">Computer Configuration > Administrative Templates > Windows Components > Remote Desktop Services > Remote Desktop Session Host</tt> and enable <strong>Allow audio and video playback redirection</strong> as well as <strong>Allow audio recording redirection</strong>.</p>
<p>Finally, reboot and you should be good to go!</p>
Atomic Test-and-Clear on the 80512020-02-29T13:00:00+01:002020-02-29T13:00:00+01:00ferdinandtag:ferdinandkeil.com,2020-02-29:/atomic-test-and-clear-8051.html<p>When running multiple tasks simultaneously on an embedded system using cooperative task scheduling you might run into situations (at least I did 😁) where these tasks might need to access the same hardware peripheral. Not all peripherals can be shared easily due to their configuration or some other kind of internal …</p><p>When running multiple tasks simultaneously on an embedded system using cooperative task scheduling you might run into situations (at least I did 😁) where these tasks might need to access the same hardware peripheral. Not all peripherals can be shared easily due to their configuration or some other kind of internal state. To coordinate access to the peripheral from multiple tasks one can use a <a class="reference external" href="https://en.wikipedia.org/wiki/Lock_(computer_science)">Lock</a>.</p>
<p>To ensure that the code managing the lock state shows deterministic behavior in a system with interrupts, special care has to be taken. The easy - but clumsy - implementation would just disable interrupts for critical code sections. This can lead to unintended dire consequences in terms of the real time behavior of the system, e.g. bytes get lost while communicating with an external system due to buffer overflow. The <em>correct™</em> way to implement the lock would be to use an atomic operation to test-and-clear the flag variable used at the core of the lock. This however needs to be supported by the MCU core in hardware.</p>
<p>Luckily, the <a class="reference external" href="https://en.wikipedia.org/wiki/Intel_MCS-51">8051-architecture</a> as used in the <a class="reference external" href="https://jaycarlson.net/pf/silicon-labs-efm8/">Silicon Labs EFM8</a> comes with just the needed instruction: <strong>JBC</strong>, or <em>jump if bit set with clear</em>. This instruction gets executed atomically, thus cannot be interrupted by an interrupt. A basic example of a lock for the Keil compiler would then look something like this:</p>
<div class="highlight"><pre><span></span><span class="cp">#include</span><span class="w"> </span><span class="cpf"><intrins.h></span><span class="cp"></span>
<span class="n">bit</span><span class="w"> </span><span class="n">Lock_unlocked</span><span class="p">;</span><span class="w"></span>
<span class="kt">uint8_t</span><span class="w"> </span><span class="nf">Lock_getLock</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">_testbit_</span><span class="p">(</span><span class="n">Lock_unlocked</span><span class="p">))</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="c1">// lock was unlocked, so we claimed it</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="c1">// lock is still locked, try again later</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
<span class="kt">void</span><span class="w"> </span><span class="nf">Lock_releaseLock</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="c1">// don't need lock anymore, so release it</span>
<span class="w"> </span><span class="n">Lock_unlocked</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</pre></div>
<p><strong>Note:</strong> The Keil compiler comes with the intrinsic function <a class="reference external" href="http://www.keil.com/support/man/docs/c51/c51__testbit_.htm">_testbit_(bit b)</a> that makes it very easy to use the <strong>JBC</strong> instruction.</p>
FIFO Size on EFM8 Parts2020-02-28T20:00:00+01:002020-02-28T20:00:00+01:00ferdinandtag:ferdinandkeil.com,2020-02-28:/fifo-size-on-efm8-parts.html<p>Recently I was working on a project using a SiLabs EFM8 LaserBee microcontroller. These parts have a very rich set of peripherals and come at a rather low price.</p>
<p>When implementing communication with a host over UART I stumbled upon on issue with the UART1's FIFO: to relax timing requirements …</p><p>Recently I was working on a project using a SiLabs EFM8 LaserBee microcontroller. These parts have a very rich set of peripherals and come at a rather low price.</p>
<p>When implementing communication with a host over UART I stumbled upon on issue with the UART1's FIFO: to relax timing requirements one can set an RX FIFO threshold and once that is reached an interrupt is generated. But no matter what value I wrote to <em>UART1FCN0_RXTH</em>, the interrupt would always fire once a single byte was received. After searching around for a while I found an article by SiLabs <a class="footnote-reference" href="#footnote-1" id="footnote-reference-1">[1]</a> explaining that the UART FIFO is only <strong>one</strong> byte deep 😑! They should have called it a register and not a FIFO...</p>
<p>That leaves one with only one option: once a byte was received by the UART it has to be read (and stored) by the user before another byte comes in and overwrites it. The "FIFO" and threshold setting are not great in terms of relaxing timing that way.</p>
<p>The FIFO size for the other peripherals is equally unintuitive, so I will repeat this info here. There are separate FIFOs for transmit and receive, e.g. UART1 has a 1 byte transmit FIFO and a 1 byte receive FIFO.</p>
<table border="1" class="docutils">
<colgroup>
<col width="36%" />
<col width="64%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Peripheral</th>
<th class="head">FIFO size (RX & TX)</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>UART1</td>
<td>1 byte</td>
</tr>
<tr><td>SMBus0</td>
<td>1 byte</td>
</tr>
<tr><td>SPI0</td>
<td>2 bytes</td>
</tr>
<tr><td>I2CSlave0</td>
<td>2 bytes</td>
</tr>
</tbody>
</table>
<p><strong>Applies to:</strong> EFM8BB2, EFM8BB3 and EFM8LB1 parts.</p>
<div class="section" id="ps">
<h2>PS</h2>
<p>The inspiration for this section (<em>"Today I Learned"</em>) came from <a class="reference external" href="https://datumorphism.com/til/">Lei Ma's awesome website</a>. Thanks for that 👍!</p>
<table class="docutils footnote" frame="void" id="footnote-1" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#footnote-reference-1">[1]</a></td><td><a class="reference external" href="https://www.silabs.com/community/mcu/8-bit/knowledge-base.entry.html/2016/07/17/efm8bb3_uart1_mbuss-wbp9">https://www.silabs.com/community/mcu/8-bit/knowledge-base.entry.html/2016/07/17/efm8bb3_uart1_mbuss-wbp9</a></td></tr>
</tbody>
</table>
</div>
Accelerated Testing Tip #1: Sealing cable ports2019-12-08T18:00:00+01:002019-12-08T18:00:00+01:00ferdinandtag:ferdinandkeil.com,2019-12-08:/accelerated-testing-tip1-sealing-cable-ports.html<div class="section" id="introduction-to-the-series">
<h2>Introduction to the Series</h2>
<p>For my PhD at the <a class="reference external" href="https://www.ies.tu-darmstadt.de/">Integrated Electronic Systems Lab</a> at <a class="reference external" href="https://www.tu-darmstadt.de/">Technische Universität Darmstadt</a> I have been running <a class="reference external" href="https://en.wikipedia.org/wiki/Accelerated_life_testing">accelerated life tests</a> for a few years now. Life tests can be quite challenging: they can take quite a long time to produce any results; you need expensive equipment …</p></div><div class="section" id="introduction-to-the-series">
<h2>Introduction to the Series</h2>
<p>For my PhD at the <a class="reference external" href="https://www.ies.tu-darmstadt.de/">Integrated Electronic Systems Lab</a> at <a class="reference external" href="https://www.tu-darmstadt.de/">Technische Universität Darmstadt</a> I have been running <a class="reference external" href="https://en.wikipedia.org/wiki/Accelerated_life_testing">accelerated life tests</a> for a few years now. Life tests can be quite challenging: they can take quite a long time to produce any results; you need expensive equipment to do them properly (e.g. a climate chamber); parts of the test setup is exposed to the accelerating conditions and thus needs be really robust to outlast the device under test. In this short series I will share some tips I have learned along the way and help you to become an accelerated testing ninja yourself 😉.</p>
<p><em>If you, dear reader, come across a more exhaustive source of tips and techniques, please let me know.</em></p>
</div>
<div class="section" id="first-tip-sealing-cable-ports">
<h2>First Tip: Sealing cable ports</h2>
<p>When you are running tests inside an oven or climate chamber it is quite common that the device under test needs to be connected to some equipment outside of the chamber. Whether this is to power the device (think of <a class="reference external" href="https://www.espec.co.jp/english/products/measure-semicon/thb/">THB tests</a>), to connect it to measurement equipment or different parts of a complex system, it always means that you need to run cables through the chamber wall. This is why these chambers usually <a class="footnote-reference" href="#footnote-1" id="footnote-reference-1">[1]</a> come with cable ports.</p>
<p>Now, whether you are running a test at high or low temperatures or at increased humidity levels, you always want to keep the simulated environment inside the chamber. This is especially important for damp heat tests: as the dew point outside the chamber is much lower, humidity will condensate when exposed to the outside and thus will be lost from the chamber. If that happens, the water consumption of the chamber can go through the roof. And of course all that water will make a huge mess in the room where the chamber is placed. So you need to <em>seal</em> your chamber.</p>
<p>The manufacturer of the chamber should be able to supply special plugs for the cable ports. I think they are made from a high-temperature-resistant silicone foam, but I might be wrong here. The important thing is, they can withstand damp heat environments. They are also relatively soft, so they seal the port quite nicely. Once bundle of cables you need to run outside the chambers grows bigger, you can't jam in the plug together with them. One solution is to remove parts of the plug with a sharp knife.</p>
<p>As I didn't want to damage the precious plugs, I found an alternative. For this I bought a <em>1 m x 1 m</em> sheet of silicone foam <a class="reference external" href="https://www.kkt-siegen.de/weitere-produkte.html">online</a>. Now to create a plug, the sheet is cut into approximately 80 mm wide strips. These are then cut to the appropriate length and rolled up to create a plug. This method cost-efficient (you get a lot of plugs from one sheet of silicone foam) and can be adapted to any port diameter.</p>
<div class="figure">
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2019/12/silicone_foam_strip.jpg"><img alt="" src="https://ferdinandkeil.com/uploads/2019/12/thumbnails/300x_/silicone_foam_strip.jpg" /></a>
<p class="caption">Narrow strip of silicone foam sheet.</p>
</div>
<p>Unfortunately, the plug alone does not seal the port very tight and water vapor can still escape. This is where the <a class="reference external" href="https://en.wikipedia.org/wiki/Plumber%27s_putty">plumbers putty</a> comes in. Plumbers putty (I'm using the brand "plastic-fermit", commonly availabel in German home improvement stores) is mainly used to create watertight seals for sinks and drains. It is a soft, pliable substance and can be worked like Play-Doh.</p>
<div class="figure">
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2019/12/plastic-fermit.jpg"><img alt="" src="https://ferdinandkeil.com/uploads/2019/12/thumbnails/300x_/plastic-fermit.jpg" /></a>
<p class="caption">Tub of "plastic-fermit" brand plumbers putty.</p>
</div>
<p>I first use it to create super tight plugs. For that, I place a rope of putty along the strip of foam sheet before rolling it up. The putty forms a seal between the layers of foam sheet, make it harder for the water vapor to find its way through. After all ports are plugged, I seal them with copious amounts of putty. There still will be some crevices between the cables, however, this approach has proven to work quite well in my experiments.</p>
<div class="figure">
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2019/12/sealed_cable_ports.jpg"><img alt="" src="https://ferdinandkeil.com/uploads/2019/12/thumbnails/300x_/sealed_cable_ports.jpg" /></a>
<p class="caption">Sealed cable ports after approx. 3000 hours at 85 °C and 85 % relH.</p>
</div>
<p>As can be seen in the picture above, these seals can easily last several thousand hours of even the most severe testing environments. However, although the plumbers putty is supposed to be long-term stable up to 100 °C, it dries up and cracks when exposed to water vapor. You can add some more later on to close the cracks or just leave it be.</p>
<table class="docutils footnote" frame="void" id="footnote-1" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#footnote-reference-1">[1]</a></td><td>If you are buying a brand-new chamber or oven, ask your supplier for the port options. They do not cost a lot and putting them in afterwards is much more difficult.</td></tr>
</tbody>
</table>
</div>
How not to replace your BIOS EEPROM2019-11-16T15:30:00+01:002019-11-16T15:30:00+01:00ferdinandtag:ferdinandkeil.com,2019-11-16:/how-not-to-replace-bios-eeprom.html<p>One of my PCs recently started freezing out of nowhere. It would freeze in the BIOS, during booting, while running. When frozen it would react to the power button, which made me curious. After ruling out all peripherals internal and external by disconnecting them, reapplying thermal paste to the CPU …</p><p>One of my PCs recently started freezing out of nowhere. It would freeze in the BIOS, during booting, while running. When frozen it would react to the power button, which made me curious. After ruling out all peripherals internal and external by disconnecting them, reapplying thermal paste to the CPU, memchecking and trying a differnt power supply I ran out of options. The final suspect was the mainboard. Before giving up I wanted to try and swap the BIOS EEPROM.</p>
<p>What made me suspicous of the BIOS EEPROM you ask? Well, every time this PC boots it programs the BIOS to wake it up during the night to run some backups. I do not know whether this setting is written to the EEPROM or the RTC RAM, but writing it often could potentially damage the EEPROM's flash.</p>
<p>So I found another EEPROM in the junk bin, got myself a CH341A-based flash programmer and off I went. Or so I thought. The EEPROM I found was a different size (8 MB vs. 1 MB for the old EEPROM). Of course <a class="reference external" href="https://www.flashrom.org/Flashrom">flashrom</a> did complain about that, but by padding the ROM image I could get it to program the larger EEPROM anyway.</p>
<p>But to no avail. The PC would not boot from this EEPROM. <strong>So, turns out you can't swap EEPROM ICs willy nilly.</strong></p>
Restore Default Alert Sound in Gnome (Ubuntu)2019-10-01T20:53:00+02:002019-10-01T20:53:00+02:00ferdinandtag:ferdinandkeil.com,2019-10-01:/restore-default-altert-sound-ubuntu.html<p>While trying to disable the terminal bell in Gnome on Ubuntu 18.04 I accidentally triggered a bug causing Gnome to play two alert sounds when triggered. The bug has been known (<a class="reference external" href="https://bugs.launchpad.net/ubuntu/+source/gnome-control-center/+bug/1753070">Ubuntu bug #1753070</a>) for quite a while now, but unfortunately has not been fixed yet. In the bug …</p><p>While trying to disable the terminal bell in Gnome on Ubuntu 18.04 I accidentally triggered a bug causing Gnome to play two alert sounds when triggered. The bug has been known (<a class="reference external" href="https://bugs.launchpad.net/ubuntu/+source/gnome-control-center/+bug/1753070">Ubuntu bug #1753070</a>) for quite a while now, but unfortunately has not been fixed yet. In the bug report <a class="reference external" href="https://launchpad.net/~ame-nomade">Ame Nomade</a> describes a solution that I will repeat here so I can find if I happen to have this problem again. I a terminal type:</p>
<div class="highlight"><pre><span></span>dconf reset /org/gnome/desktop/sound/theme-name
</pre></div>
<p>This resets the key to its default value.</p>
<p>PS: The terminal bell can be deactivated in the settings of the terminal itself, so messing with Gnome's settings is not necessary.</p>
Installing Star Trek: Captain's Chair on Linux2019-02-12T18:51:00+01:002019-02-12T18:51:00+01:00ferdinandtag:ferdinandkeil.com,2019-02-12:/installing-star-trek-captains-chair-wine.html<p>Being a long time fan of Star Trek I recently came across the Simon & Schuster game <a class="reference external" href="https://memory-alpha.fandom.com/wiki/Star_Trek:_Captain%27s_Chair">Star Trek - Captain's Chair</a> from 1997. It's basically a simulation of the Captain's bridge of five different Federation starships, most importantly (IMHO) the one of the <a class="reference external" href="https://memory-alpha.fandom.com/wiki/USS_Enterprise_(NCC-1701-E)">USS Enterprise NCC-1701-E</a> from Star Trek: The First …</p><p>Being a long time fan of Star Trek I recently came across the Simon & Schuster game <a class="reference external" href="https://memory-alpha.fandom.com/wiki/Star_Trek:_Captain%27s_Chair">Star Trek - Captain's Chair</a> from 1997. It's basically a simulation of the Captain's bridge of five different Federation starships, most importantly (IMHO) the one of the <a class="reference external" href="https://memory-alpha.fandom.com/wiki/USS_Enterprise_(NCC-1701-E)">USS Enterprise NCC-1701-E</a> from Star Trek: The First Contact.</p>
<p>Physical copies of the game are available from the usual sources and are not prohibitively expensive. But as luck would have it, the game has been archived by <em>archive.org</em> (<a class="reference external" href="https://archive.org/details/star-trek-captains-chair">direct link</a>). Just download the ISO-image, mount it and hop onto your favorite bridge.</p>
<div class="section" id="installation">
<h2>Installation</h2>
<p>However, if you're not running some ancient version of Windows on your machine (or in a VM) but use a recent Linux instead you will have use <a class="reference external" href="https://www.winehq.org/">wine</a> to get it working. Here are the necessary steps.</p>
<p>First, start with a clean 32bit wine-prefix:</p>
<div class="highlight"><pre><span></span><span class="nv">WINEPREFIX</span><span class="o">=</span>~/.wine.captains-chair <span class="nv">WINEARCH</span><span class="o">=</span>win32 winecfg
</pre></div>
<p>Set <em>Windows-Version</em> to <em>Windows 98</em> and while your at it make wine emulate a desktop with an 640x480 resolution. The game does not support higher resolutions anyway. I suppose you went ahead and mounted the ISO-image. Then run:</p>
<div class="highlight"><pre><span></span><span class="nv">WINEPREFIX</span><span class="o">=</span>~/.wine.captains-chair <span class="nv">WINEARCH</span><span class="o">=</span>win32 wine ~/.cdrom/setup.exe
</pre></div>
<p>You <strong>absolutely</strong> need to install the included QuickTime runtime for the game to work. Just skip the scan for previous versions during the installation of QuickTime.</p>
</div>
<div class="section" id="patching-director-player-5-0">
<h2>Patching Director Player 5.0</h2>
<p>The game will not work as of now as the binary contains some ancient bug related to <em>Director Player 5.0</em>. Ancient bugs require ancient patches and in this case <a class="reference external" href="https://www.sacah.net/2008/01/how-to-edit-director-player-60-to-stop.html">*sacah* has created one</a> in 2008 and shared it with the world. Run the patcher using wine and select <tt class="docutils literal"><span class="pre">C:\Captain's</span> Chair\Source\Cap_win.exe</tt>.</p>
</div>
<div class="section" id="no-cd-crack">
<h2>No-CD "Crack"</h2>
<p>Now you can run the game. However, it will stop working once you unmount the ISO-image due to its copy protection. The implementation seems to be quite primitive, so all you need to do is to add an additional drive in <em>winecfg</em> and put a file named <tt class="docutils literal">imergy.txt</tt> with the following content:</p>
<!-- -->
<blockquote>
Find CD letter!!!</blockquote>
<p>No, that's not a joke. The file is actually part of the image file.</p>
<p>Now have fun exploring!</p>
</div>
Fixing cups-lpd on Raspbian Jessie2017-06-22T22:29:00+02:002017-06-22T22:29:00+02:00ferdinandtag:ferdinandkeil.com,2017-06-22:/fixing-cups-lpd-on-raspbian-jessie.html<p>As I have <a class="reference external" href="https://ferdinandkeil.com/read-only-filesystem-for-raspberry-pi.html">mentioned before</a> I use a Raspberry Pi running Rasbian Jessie as a print-server. After I made the <a class="reference external" href="https://ferdinandkeil.com/setting-up-cups-with-lpr-on-raspbian.html">switch to LPR</a> I started noticing new problems: some documents just wouldn't print. Printing web-pages from Firefox stopped working alltogether. So what now?</p>
<p>What were the symptoms? Whenever I tried …</p><p>As I have <a class="reference external" href="https://ferdinandkeil.com/read-only-filesystem-for-raspberry-pi.html">mentioned before</a> I use a Raspberry Pi running Rasbian Jessie as a print-server. After I made the <a class="reference external" href="https://ferdinandkeil.com/setting-up-cups-with-lpr-on-raspbian.html">switch to LPR</a> I started noticing new problems: some documents just wouldn't print. Printing web-pages from Firefox stopped working alltogether. So what now?</p>
<p>What were the symptoms? Whenever I tried to print one of the offending documents, these lines showed up in <em>/var/log/cups/error_log</em>:</p>
<div class="highlight"><pre><span></span>W [15/Jun/2017:15:44:32 +0000] Unexpected 'document-name' operation attribute in a Create-Job request.
E [15/Jun/2017:15:44:32 +0000] [Client 17] Returning IPP client-error-attributes-or-values-not-supported for Create-Job (ipp://localhost/printers/Samsung_ML-2010) from localhost
</pre></div>
<p>With the CUPS release used in Raspbian Jessie being around since 2014 there was a good chance someone else has had these problems before. And indeed, I was lucky.</p>
<div class="section" id="unexpected-document-name-operation-attribute-in-a-create-job-request">
<h2>Unexpected 'document-name' operation attribute in a Create-Job request.</h2>
<p>So what is happening here? Well, the cups-lpd mini daemon is sending a <em>document-name</em> attribute via IPP to CUPS when creating a new job. But, CUPS does not expect this attribute and starts complaining. You can read more about it in <a class="reference external" href="https://github.com/apple/cups/issues/4790">issue #4790</a>. These are the necessary changes to <em>cups-lpd.c</em> :</p>
<div class="line-block">
<div class="line"><br /></div>
</div>
<div class="highlight"><pre><span></span><span class="gu">@@ -344,10 +345,6 @@ create_job(http_t *http, /* I - HTTP connection */</span><span class="w"></span>
<span class="w"> </span> ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name",<span class="w"></span>
<span class="w"> </span> NULL, title);<span class="w"></span>
<span class="gd">- if (docname[0])</span><span class="w"></span>
<span class="gd">- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "document-name",</span><span class="w"></span>
<span class="gd">- NULL, docname);</span><span class="w"></span>
<span class="gd">-</span><span class="w"></span>
<span class="w"> </span> cupsEncodeOptions(request, num_options, options);<span class="w"></span>
<span class="w"> </span> /*<span class="w"></span>
</pre></div>
<p>This basically just removes the lines responsible for sending the unwanted <em>document-name</em> attribute.</p>
</div>
<div class="section" id="returning-ipp-client-error-attributes-or-values-not-supported">
<h2>Returning IPP client-error-attributes-or-values-not-supported</h2>
<p>This one is a little tougher. Turns out, it's a problem with <a class="reference external" href="https://xkcd.com/1209/">Unicode support</a>. More details can be found in <cite>issue #4899<https://github.com/apple/cups/issues/4899></cite>. To get rid of it I applied some of the changes from commit <cite>5babee8<https://github.com/apple/cups/commit/5babee86cb84055bce3597ab537abe4a6c6d8dbc></cite> to the code:</p>
<div class="highlight"><pre><span></span><span class="gu">@@ -71,6 +71,7 @@ static int remove_jobs(const char *name, const char *agent,</span><span class="w"></span>
<span class="w"> </span>static int send_state(const char *name, const char *list,<span class="w"></span>
<span class="w"> </span> int longstatus);<span class="w"></span>
<span class="w"> </span>static char *smart_gets(char *s, int len, FILE *fp);<span class="w"></span>
<span class="gi">+static void smart_strlcpy(char *dst, const char *src, size_t dstsize);</span><span class="w"></span>
<span class="w"> </span>/*<span class="w"></span>
<span class="gu">@@ -1043,15 +1040,15 @@ recv_print_job(</span><span class="w"></span>
<span class="w"> </span> switch (line[0])<span class="w"></span>
<span class="w"> </span> {<span class="w"></span>
<span class="w"> </span> case 'J' : /* Job name */<span class="w"></span>
<span class="gd">- strlcpy(title, line + 1, sizeof(title));</span><span class="w"></span>
<span class="gi">+ smart_strlcpy(title, line + 1, sizeof(title));</span><span class="w"></span>
<span class="w"> </span> break;<span class="w"></span>
<span class="w"> </span> case 'N' : /* Document name */<span class="w"></span>
<span class="gd">- strlcpy(docname, line + 1, sizeof(docname));</span><span class="w"></span>
<span class="gi">+ smart_strlcpy(docname, line + 1, sizeof(docname));</span><span class="w"></span>
<span class="w"> </span> break;<span class="w"></span>
<span class="w"> </span> case 'P' : /* User identification */<span class="w"></span>
<span class="gd">- strlcpy(user, line + 1, sizeof(user));</span><span class="w"></span>
<span class="gi">+ smart_strlcpy(user, line + 1, sizeof(user));</span><span class="w"></span>
<span class="w"> </span> break;<span class="w"></span>
<span class="w"> </span> case 'L' : /* Print banner page */<span class="w"></span>
<span class="gu">@@ -1136,7 +1133,7 @@ recv_print_job(</span><span class="w"></span>
<span class="w"> </span> switch (line[0])<span class="w"></span>
<span class="w"> </span> {<span class="w"></span>
<span class="w"> </span> case 'N' : /* Document name */<span class="w"></span>
<span class="gd">- strlcpy(docname, line + 1, sizeof(docname));</span><span class="w"></span>
<span class="gi">+ smart_strlcpy(docname, line + 1, sizeof(docname));</span><span class="w"></span>
<span class="w"> </span> break;<span class="w"></span>
<span class="w"> </span> case 'c' : /* Plot CIF file */<span class="w"></span>
<span class="gu">@@ -1612,5 +1609,96 @@ smart_gets(char *s, /* I - Pointer to line buffer */</span><span class="w"></span>
<span class="w"> </span>/*<span class="w"></span>
<span class="gi">+ * 'smart_strlcpy()' - Copy a string and convert from ISO-8859-1 to UTF-8 as needed.</span><span class="w"></span>
<span class="gi">+ */</span><span class="w"></span>
<span class="gi">+</span><span class="w"></span>
<span class="gi">+static void</span><span class="w"></span>
<span class="gi">+smart_strlcpy(char *dst, /* I - Output buffer */</span><span class="w"></span>
<span class="gi">+ const char *src, /* I - Input string */</span><span class="w"></span>
<span class="gi">+ size_t dstsize) /* I - Size of output buffer */</span><span class="w"></span>
<span class="gi">+{</span><span class="w"></span>
<span class="gi">+ const unsigned char *srcptr; /* Pointer into input string */</span><span class="w"></span>
<span class="gi">+ unsigned char *dstptr, /* Pointer into output buffer */</span><span class="w"></span>
<span class="gi">+ *dstend; /* End of output buffer */</span><span class="w"></span>
<span class="gi">+ int saw_8859 = 0; /* Saw an extended character that was not UTF-8? */</span><span class="w"></span>
<span class="gi">+</span><span class="w"></span>
<span class="gi">+</span><span class="w"></span>
<span class="gi">+ for (srcptr = (unsigned char *)src, dstptr = (unsigned char *)dst, dstend = dstptr + dstsize - 1; *srcptr;)</span><span class="w"></span>
<span class="gi">+ {</span><span class="w"></span>
<span class="gi">+ if (*srcptr < 0x80)</span><span class="w"></span>
<span class="gi">+ *dstptr++ = *srcptr++; /* ASCII */</span><span class="w"></span>
<span class="gi">+ else if (saw_8859)</span><span class="w"></span>
<span class="gi">+ {</span><span class="w"></span>
<span class="gi">+ /*</span><span class="w"></span>
<span class="gi">+ * Map ISO-8859-1 (most likely character set for legacy LPD clients) to</span><span class="w"></span>
<span class="gi">+ * UTF-8...</span><span class="w"></span>
<span class="gi">+ */</span><span class="w"></span>
<span class="gi">+</span><span class="w"></span>
<span class="gi">+ if (dstptr > (dstend - 2))</span><span class="w"></span>
<span class="gi">+ break;</span><span class="w"></span>
<span class="gi">+</span><span class="w"></span>
<span class="gi">+ *dstptr++ = 0xc0 | (*srcptr >> 6);</span><span class="w"></span>
<span class="gi">+ *dstptr++ = 0x80 | (*srcptr++ & 0x3f);</span><span class="w"></span>
<span class="gi">+ }</span><span class="w"></span>
<span class="gi">+ else if ((*srcptr & 0xe0) == 0xc0 && (srcptr[1] & 0xc0) == 0x80)</span><span class="w"></span>
<span class="gi">+ {</span><span class="w"></span>
<span class="gi">+ /*</span><span class="w"></span>
<span class="gi">+ * 2-byte UTF-8 sequence...</span><span class="w"></span>
<span class="gi">+ */</span><span class="w"></span>
<span class="gi">+</span><span class="w"></span>
<span class="gi">+ if (dstptr > (dstend - 2))</span><span class="w"></span>
<span class="gi">+ break;</span><span class="w"></span>
<span class="gi">+</span><span class="w"></span>
<span class="gi">+ *dstptr++ = *srcptr++;</span><span class="w"></span>
<span class="gi">+ *dstptr++ = *srcptr++;</span><span class="w"></span>
<span class="gi">+ }</span><span class="w"></span>
<span class="gi">+ else if ((*srcptr & 0xf0) == 0xe0 && (srcptr[1] & 0xc0) == 0x80 && (srcptr[2] & 0xc0) == 0x80)</span><span class="w"></span>
<span class="gi">+ {</span><span class="w"></span>
<span class="gi">+ /*</span><span class="w"></span>
<span class="gi">+ * 3-byte UTF-8 sequence...</span><span class="w"></span>
<span class="gi">+ */</span><span class="w"></span>
<span class="gi">+</span><span class="w"></span>
<span class="gi">+ if (dstptr > (dstend - 3))</span><span class="w"></span>
<span class="gi">+ break;</span><span class="w"></span>
<span class="gi">+</span><span class="w"></span>
<span class="gi">+ *dstptr++ = *srcptr++;</span><span class="w"></span>
<span class="gi">+ *dstptr++ = *srcptr++;</span><span class="w"></span>
<span class="gi">+ *dstptr++ = *srcptr++;</span><span class="w"></span>
<span class="gi">+ }</span><span class="w"></span>
<span class="gi">+ else if ((*srcptr & 0xf8) == 0xf0 && (srcptr[1] & 0xc0) == 0x80 && (srcptr[2] & 0xc0) == 0x80 && (srcptr[3] & 0xc0) == 0x80)</span><span class="w"></span>
<span class="gi">+ {</span><span class="w"></span>
<span class="gi">+ /*</span><span class="w"></span>
<span class="gi">+ * 4-byte UTF-8 sequence...</span><span class="w"></span>
<span class="gi">+ */</span><span class="w"></span>
<span class="gi">+</span><span class="w"></span>
<span class="gi">+ if (dstptr > (dstend - 4))</span><span class="w"></span>
<span class="gi">+ break;</span><span class="w"></span>
<span class="gi">+</span><span class="w"></span>
<span class="gi">+ *dstptr++ = *srcptr++;</span><span class="w"></span>
<span class="gi">+ *dstptr++ = *srcptr++;</span><span class="w"></span>
<span class="gi">+ *dstptr++ = *srcptr++;</span><span class="w"></span>
<span class="gi">+ *dstptr++ = *srcptr++;</span><span class="w"></span>
<span class="gi">+ }</span><span class="w"></span>
<span class="gi">+ else</span><span class="w"></span>
<span class="gi">+ {</span><span class="w"></span>
<span class="gi">+ /*</span><span class="w"></span>
<span class="gi">+ * Bad UTF-8 sequence, this must be an ISO-8859-1 string...</span><span class="w"></span>
<span class="gi">+ */</span><span class="w"></span>
<span class="gi">+</span><span class="w"></span>
<span class="gi">+ saw_8859 = 1;</span><span class="w"></span>
<span class="gi">+</span><span class="w"></span>
<span class="gi">+ if (dstptr > (dstend - 2))</span><span class="w"></span>
<span class="gi">+ break;</span><span class="w"></span>
<span class="gi">+</span><span class="w"></span>
<span class="gi">+ *dstptr++ = 0xc0 | (*srcptr >> 6);</span><span class="w"></span>
<span class="gi">+ *dstptr++ = 0x80 | (*srcptr++ & 0x3f);</span><span class="w"></span>
<span class="gi">+ }</span><span class="w"></span>
<span class="gi">+ }</span><span class="w"></span>
<span class="gi">+</span><span class="w"></span>
<span class="gi">+ *dstptr = '\0';</span><span class="w"></span>
<span class="gi">+}</span><span class="w"></span>
<span class="gi">+</span><span class="w"></span>
<span class="gi">+</span><span class="w"></span>
<span class="gi">+/*</span><span class="w"></span>
<span class="w"> </span> * End of "$Id: cups-lpd.c 11623 2014-02-19 20:18:10Z msweet $".<span class="w"></span>
<span class="w"> </span> */<span class="w"></span>
</pre></div>
<p>Well, that did it.</p>
<p>Now, how does one compile their own <em>.deb</em> package?</p>
</div>
<div class="section" id="applying-the-changes-and-compiling-the-module">
<h2>Applying the changes and compiling the module</h2>
<p>I followed the tutorial on debian.org for <a class="reference external" href="https://wiki.debian.org/BuildingTutorial">building packages</a>. Some of the steps didn't work for me and couldn't be bothered to find out why. Here is what I ended up doing:</p>
<div class="highlight"><pre><span></span>sudo nano /etc/apt/sources.list
<span class="c1"># uncomment the line starting with deb-src</span>
sudo apt-get update
sudo apt-get install -y build-essential fakeroot devscripts
sudo apt-get build-dep -y cups
mkdir -p src/debian
<span class="nb">cd</span> src/debian
apt-get <span class="nb">source</span> cups
<span class="nb">cd</span> cups-1.7.5
nano schedules/cups-lpd.c
<span class="c1"># apply the changes mentioned above</span>
debuild -b -uc -us -tc
<span class="c1"># ^- that builds the package, so it might take a while</span>
</pre></div>
<p>This results in several packages being build, however you only need <em>cups_1.7.5-11+deb8u1_armhf.deb</em>. To install it type:</p>
<div class="highlight"><pre><span></span>sudo dpkg -i cups_1.7.5-11+deb8u1_armhf.deb
</pre></div>
</div>
<div class="section" id="tl-dr">
<h2>TL;DR</h2>
<p>The <em>cups-lpd</em> coming with Raspbian Jessie is broken and will not print certain documents. Install the package below to get rid of these problems.</p>
<div class="line-block">
<div class="line"><br /></div>
</div>
<a href="https://ferdinandkeil.com/uploads/2017/06/cups_1.7.5-11+deb8u1_armhf.deb"><i class="fa fa-floppy-o fa-2x" aria-hidden="true"></i> cups_1.7.5-11+deb8u1_armhf.deb</a></div>
Setting up CUPS with LPR on Raspbian2017-01-15T15:56:00+01:002017-01-15T15:56:00+01:00ferdinandtag:ferdinandkeil.com,2017-01-15:/setting-up-cups-with-lpr-on-raspbian.html<p>With CUPS you can easily set up a Raspberry Pi as print-server. Out of
the box client can connect to CUPS over IPP (<a class="reference external" href="https://en.wikipedia.org/wiki/Internet_Printing_Protocol">Wiki - Internet Printing
Protocol</a>).
However, on Windows machines this have unwanted side-effects whenever
the server is turned off: everytime I opened a document in LibreOffice
the program …</p><p>With CUPS you can easily set up a Raspberry Pi as print-server. Out of
the box client can connect to CUPS over IPP (<a class="reference external" href="https://en.wikipedia.org/wiki/Internet_Printing_Protocol">Wiki - Internet Printing
Protocol</a>).
However, on Windows machines this have unwanted side-effects whenever
the server is turned off: everytime I opened a document in LibreOffice
the program froze for more than a minute. This is due to the Windows
Spooler searching for the print-server until a time-out occurs. This
behavior can be avoided by using the LPR protocol (<a class="reference external" href="https://en.wikipedia.org/wiki/Line_Printer_Daemon_protocol">Wiki - Line Printer
Daemon
protocol</a>).
In the following I will describe the necessary steps for this setup.</p>
<p>I tried this on a Raspberry Pi 1 running Raspbian Jessie Lite
(2016-11-25).</p>
<p><strong>Step 1</strong></p>
<p>First you'll have to install CUPS. For LPR to work you'll also need
xinetd. And I also needed splix as it contains the driver for my printer
(Samsung ML-2010PR).</p>
<div class="highlight"><pre><span></span>sudo apt-get install -y splix cups xinetd
sudo cupsctl --share-printers --remote-admin
sudo usermod -a -G lpadmin pi
</pre></div>
<p>The second commands enables printer-sharing and the CUPS web-interface.
The last command allows the user <tt class="docutils literal">pi</tt> to change the settings for CUPS.</p>
<p><strong>Step 2</strong></p>
<p>To enable LPR you'll have to configure xinetd. Create a new config file
named <tt class="docutils literal"><span class="pre">cups-lpd</span></tt> in <tt class="docutils literal">/etc/xinetd.d</tt>:</p>
<div class="highlight"><pre><span></span>sudo nano /etc/xinetd.d/cups-lpd
</pre></div>
<p>Paste the following configuration into the file:</p>
<div class="highlight"><pre><span></span>service printer
{
socket_type = stream
protocol = tcp
wait = no
user = lp
server = /usr/lib/cups/daemon/cups-lpd
server_args = -o document-format=application/octet-stream -o job-sheets=none,none
disable = no
}
</pre></div>
<p>Then restart xinetd:</p>
<div class="highlight"><pre><span></span>sudo /etc/init.d/xinetd restart
</pre></div>
<p><strong>Step 3 and Finish</strong></p>
<p>Now add your printer through the CUPS web-interface. It can by found at
<a class="reference external" href="https://YOUR-IP:631/admin">https://YOUR-IP:631/admin</a> and use the credentials for the standard user
<tt class="docutils literal">pi</tt>. Make sure you enable network sharing. Then you can add the
printer on the clients. For Windows you have to add a <em>Generic Network
Interface</em>. Make sure to set the queue name to the one you chose in the
web-interface. <strong>Also, you have to enable LPR Byte Counting or it will
not work!</strong></p>
Read-only Filesystem for Raspberry Pi2017-01-15T15:35:00+01:002017-01-15T15:35:00+01:00ferdinandtag:ferdinandkeil.com,2017-01-15:/read-only-filesystem-for-raspberry-pi.html<p>I recently set up a Raspberry Pi as a print- and scan-server. I want to
be able to just turn off the Raspberry Pi without a proper shutdown, so
to prevent SD-card corruption a read-only filesystem was needed. The
easy way to implement this is to just mount the root …</p><p>I recently set up a Raspberry Pi as a print- and scan-server. I want to
be able to just turn off the Raspberry Pi without a proper shutdown, so
to prevent SD-card corruption a read-only filesystem was needed. The
easy way to implement this is to just mount the root filesystem as
read-only. An unwanted side-effect of this is that all writes to the
filesystem fail. The superior solution uses a read-only root with an
overlay stored in RAM. Luckily <em>ejolson</em> on the Raspberry Pi forum has
written a <a class="reference external" href="https://www.raspberrypi.org/forums/viewtopic.php?f=63&t=161416">nice
tutorial</a>
to implement this.</p>
<p>I successfully configured Raspbian Jessie Lite (2016-11-25) running on a
Raspberry Pi 1. I have not tested it with any other Pi, but they should
work just as well. <strong>If you try this tutorial with a more recent
Raspbian version it might not work!</strong></p>
<p><em>Update:</em> Still works with a Raspberry Pi 1 and Raspbian Stretch Lite (2018-04-18).</p>
<p><strong>Step 1</strong></p>
<p>Change into a root shell and change to <tt class="docutils literal"><span class="pre">/usr/share/initramfs-tools</span></tt> by
typing:</p>
<div class="highlight"><pre><span></span>sudo bash
<span class="nb">cd</span> /usr/share/initramfs-tools <span class="c1"># type into root shell</span>
</pre></div>
<p>You have to change the file <tt class="docutils literal"><span class="pre">hook-functions</span></tt>. Just add <tt class="docutils literal">overlay</tt> to
the modules in line 528.</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">515</span>
<span class="normal">516</span>
<span class="normal">517</span>
<span class="normal">518</span>
<span class="normal">519</span>
<span class="normal">520</span>
<span class="normal">521</span>
<span class="normal">522</span>
<span class="normal">523</span>
<span class="normal">524</span>
<span class="normal">525</span>
<span class="normal">526</span>
<span class="normal">527</span>
<span class="normal">528</span>
<span class="normal">529</span>
<span class="normal">530</span>
<span class="normal">531</span>
<span class="normal">532</span>
<span class="normal">533</span>
<span class="normal">534</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># The modules "most" classes added per default to the initramfs</span>
auto_add_modules<span class="o">()</span>
<span class="o">{</span>
<span class="nb">local</span> arg
<span class="nb">local</span> <span class="nv">modules</span><span class="o">=</span>
<span class="k">if</span> <span class="o">[</span> <span class="s2">"</span><span class="nv">$#</span><span class="s2">"</span> -eq <span class="m">0</span> <span class="o">]</span> <span class="p">;</span> <span class="k">then</span>
<span class="nb">set</span> -- base net ide scsi block ata i2o dasd ieee1394 firewire mmc usb_storage
<span class="k">fi</span>
<span class="k">for</span> arg <span class="k">in</span> <span class="s2">"</span><span class="nv">$@</span><span class="s2">"</span> <span class="p">;</span> <span class="k">do</span>
<span class="k">case</span> <span class="s2">"</span><span class="nv">$arg</span><span class="s2">"</span> <span class="k">in</span>
base<span class="o">)</span>
<span class="hll"> <span class="nv">modules</span><span class="o">=</span><span class="s2">"</span><span class="nv">$modules</span><span class="s2"> ehci-pci ehci-orion ehci-hcd ohci-hcd ohci-pci uhci-hcd usbhid overlay"</span>
</span> <span class="nv">modules</span><span class="o">=</span><span class="s2">"</span><span class="nv">$modules</span><span class="s2"> xhci xhci-pci xhci-hcd"</span>
<span class="nv">modules</span><span class="o">=</span><span class="s2">"</span><span class="nv">$modules</span><span class="s2"> btrfs ext2 ext3 ext4 ext4dev "</span>
<span class="nv">modules</span><span class="o">=</span><span class="s2">"</span><span class="nv">$modules</span><span class="s2"> isofs jfs reiserfs udf xfs"</span>
<span class="nv">modules</span><span class="o">=</span><span class="s2">"</span><span class="nv">$modules</span><span class="s2"> nfs nfsv2 nfsv3 nfsv4"</span>
<span class="nv">modules</span><span class="o">=</span><span class="s2">"</span><span class="nv">$modules</span><span class="s2"> af_packet atkbd i8042 psmouse"</span>
<span class="nv">modules</span><span class="o">=</span><span class="s2">"</span><span class="nv">$modules</span><span class="s2"> virtio_pci virtio_mmio"</span>
</pre></div>
</td></tr></table><p>You can find my version on Gist: <a class="reference external" href="https://gist.github.com/ferdinandkeil/827212e9d897bd6e5db71bb1aef2c708">/usr/share/initramfs-tools/hook-functions</a>.</p>
<p>This takes care of loading the overlay module at boot time.</p>
<p><strong>Step 2</strong></p>
<p>Next, you have to create a new boot script. Change to
<tt class="docutils literal"><span class="pre">/usr/share/initramfs-tools/scripts</span></tt> and copy the existing boot
script. Don't worry if the last command fails, it will still work.</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span> /usr/share/initramfs-tools/scripts
cp <span class="nb">local</span> overlay
cp -rp local-premount overlay-premount
cp -rp local-bottom overlay-bottom <span class="c1"># don't mind if this fails</span>
</pre></div>
<p>Now you'll have to change the file <tt class="docutils literal">overlay</tt> to mount the root
read-only. The changes start in line 138.</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">136</span>
<span class="normal">137</span>
<span class="normal">138</span>
<span class="normal">139</span>
<span class="normal">140</span>
<span class="normal">141</span>
<span class="normal">142</span>
<span class="normal">143</span>
<span class="normal">144</span>
<span class="normal">145</span>
<span class="normal">146</span>
<span class="normal">147</span>
<span class="normal">148</span>
<span class="normal">149</span>
<span class="normal">150</span>
<span class="normal">151</span>
<span class="normal">152</span>
<span class="normal">153</span>
<span class="normal">154</span>
<span class="normal">155</span>
<span class="normal">156</span>
<span class="normal">157</span>
<span class="normal">158</span>
<span class="normal">159</span>
<span class="normal">160</span>
<span class="normal">161</span>
<span class="normal">162</span>
<span class="normal">163</span>
<span class="normal">164</span>
<span class="normal">165</span>
<span class="normal">166</span>
<span class="normal">167</span>
<span class="normal">168</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="nv">ROOT</span><span class="o">=</span><span class="k">$(</span>resolve_device <span class="s2">"</span><span class="nv">$ROOT</span><span class="s2">"</span><span class="k">)</span>
<span class="hll"><span class="c1"># if [ "${readonly}" = "y" ]; then</span>
</span><span class="hll"><span class="c1"># roflag=-r</span>
</span><span class="hll"><span class="c1"># else</span>
</span><span class="hll"><span class="c1"># roflag=-w</span>
</span><span class="hll"><span class="c1"># fi</span>
</span>
<span class="c1"># FIXME This has no error checking</span>
modprobe <span class="si">${</span><span class="nv">FSTYPE</span><span class="si">}</span>
checkfs <span class="si">${</span><span class="nv">ROOT</span><span class="si">}</span> root
<span class="c1"># FIXME This has no error checking</span>
<span class="c1"># Mount root</span>
<span class="hll"><span class="c1"># if [ "${FSTYPE}" != "unknown" ]; then</span>
</span><span class="hll"><span class="c1"># mount ${roflag} -t ${FSTYPE} ${ROOTFLAGS} ${ROOT} ${rootmnt}</span>
</span><span class="hll"><span class="c1"># else</span>
</span><span class="hll"><span class="c1"># mount ${roflag} ${ROOTFLAGS} ${ROOT} ${rootmnt}</span>
</span><span class="hll"><span class="c1"># fi</span>
</span><span class="hll"> mkdir /upper /lower
</span><span class="hll"> <span class="k">if</span> <span class="o">[</span> <span class="s2">"</span><span class="si">${</span><span class="nv">FSTYPE</span><span class="si">}</span><span class="s2">"</span> !<span class="o">=</span> <span class="s2">"unknown"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
</span><span class="hll"> mount <span class="si">${</span><span class="nv">roflag</span><span class="si">}</span> -t <span class="si">${</span><span class="nv">FSTYPE</span><span class="si">}</span> <span class="si">${</span><span class="nv">ROOTFLAGS</span><span class="si">}</span> <span class="si">${</span><span class="nv">ROOT</span><span class="si">}</span> /lower
</span><span class="hll"> <span class="k">else</span>
</span><span class="hll"> mount <span class="si">${</span><span class="nv">roflag</span><span class="si">}</span> <span class="si">${</span><span class="nv">ROOTFLAGS</span><span class="si">}</span> <span class="si">${</span><span class="nv">ROOT</span><span class="si">}</span> /lower
</span><span class="hll"> <span class="k">fi</span>
</span><span class="hll"> modprobe overlay
</span><span class="hll"> mount -t tmpfs tmpfs /upper
</span><span class="hll"> mkdir /upper/data /upper/work
</span><span class="hll"> mount -t overlay <span class="se">\</span>
</span><span class="hll"> -olowerdir<span class="o">=</span>/lower,upperdir<span class="o">=</span>/upper/data,workdir<span class="o">=</span>/upper/work <span class="se">\</span>
</span><span class="hll"> overlay <span class="si">${</span><span class="nv">rootmnt</span><span class="si">}</span>
</span><span class="o">}</span>
</pre></div>
</td></tr></table><p>Gist: <a class="reference external" href="https://gist.github.com/ferdinandkeil/a929b50b36b7cc106b6c0853ba91700d">/usr/share/initramfs-tools/scripts/overlay</a></p>
<p><strong>Step 3 (Raspberry Pi 1, Zero, B+)</strong></p>
<p>You can now generate a suitable <tt class="docutils literal">initramfs</tt>. However, you'll have to
determine the kernel version first. In this example it is <tt class="docutils literal">4.4.34+</tt>.
For a Raspberry Pi 2 or later it would be <tt class="docutils literal"><span class="pre">4.4.34-v7+</span></tt> (notice the
v7). Now you can run <tt class="docutils literal"><span class="pre">update-initramfs</span></tt> using the kernel version.
Then you just rename the resulting file.</p>
<p><em>Update:</em> the command below takes care of determining the correct Kernel version.</p>
<div class="highlight"><pre><span></span>update-initramfs -c -k <span class="s2">"</span><span class="k">$(</span>uname -r<span class="k">)</span><span class="s2">"</span>
mv <span class="s2">"/boot/initrd.img-</span><span class="k">$(</span>uname -r<span class="k">)</span><span class="s2">"</span> /boot/initrd.img
</pre></div>
<p>Now you have to tell the bootloader to load the <tt class="docutils literal">initramfs</tt>. This can
be done by adding the following lines to <tt class="docutils literal">/boot/config.txt</tt>:</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">55</span>
<span class="normal">56</span>
<span class="normal">57</span>
<span class="normal">58</span>
<span class="normal">59</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># Enable audio (loads snd_bcm2835)</span>
<span class="nv">dtparam</span><span class="o">=</span><span class="nv">audio</span><span class="o">=</span>on
<span class="hll"><span class="nv">kernel</span><span class="o">=</span>kernel.img
</span><span class="hll">initramfs initrd.img
</span></pre></div>
</td></tr></table><p>Gist: <a class="reference external" href="https://gist.github.com/ferdinandkeil/d921b6ec4d53f19eb44a09df2c2fba7f">/boot/config.txt</a></p>
<p><strong>Step 3 (Raspberry Pi 2 and later)</strong></p>
<p>As the later Raspberry Pi models use a different CPU, the output of
<tt class="docutils literal">uname</tt> will have an additional <tt class="docutils literal">v7</tt> in the kernel version (e.g.
<tt class="docutils literal"><span class="pre">4.4.34-v7+</span></tt>). The commands change to:</p>
<div class="highlight"><pre><span></span>uname -a
<span class="c1"># Linux raspberrypi 4.4.34-v7+ #930 Wed Nov 23 15:12:30 GMT 2016</span>
armv6l GNU/Linux
update-initramfs -c -k <span class="m">4</span>.4.34-v7+
<span class="nb">cd</span> /boot
mv initrd.img-4.4.34-v7+ initrd7.img
</pre></div>
<p>Notice the 7 in <tt class="docutils literal">initrd7.img</tt>. Now change <tt class="docutils literal">/boot/config.txt</tt>:</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">55</span>
<span class="normal">56</span>
<span class="normal">57</span>
<span class="normal">58</span>
<span class="normal">59</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1"># Enable audio (loads snd_bcm2835)</span>
<span class="nv">dtparam</span><span class="o">=</span><span class="nv">audio</span><span class="o">=</span>on
<span class="hll"><span class="nv">kernel</span><span class="o">=</span>kernel7.img
</span><span class="hll">initramfs initrd7.img
</span></pre></div>
</td></tr></table><p><strong>Step 4</strong></p>
<p>The last step is to change the boot command. Just add <tt class="docutils literal">boot=overlay</tt>
to the command in <tt class="docutils literal">/boot/cmdline.txt</tt>:</p>
<div class="highlight"><pre><span></span><span class="nv">boot</span><span class="o">=</span>overlay dwc_otg.lpm_enable<span class="o">=</span><span class="m">0</span> <span class="nv">console</span><span class="o">=</span>serial0,115200 <span class="nv">console</span><span class="o">=</span>tty1 <span class="nv">root</span><span class="o">=</span>/dev/mmcblk0p2 <span class="nv">rootfstype</span><span class="o">=</span>ext4 <span class="nv">elevator</span><span class="o">=</span>deadline fsck.repair<span class="o">=</span>yes rootwait fastboot noswap
</pre></div>
<p>To disable the overlay this string has to be removed. As this file is
found in the FAT-formatted boot partition this can be done by inserting
the SD-card into a Windows PC as well. Notice that I have also added
<tt class="docutils literal">fastboot</tt> and <tt class="docutils literal">noswap</tt> to the command. These options disable
filesystem checking at boot and the swap.</p>
<p><strong>Finish</strong></p>
<p>If you have followed all the steps you can now reboot. After reboot run
<tt class="docutils literal">df</tt> to see if it worked.</p>
<div class="highlight"><pre><span></span>df
<span class="c1"># Filesystem 1K-blocks Used Available Use% Mounted on</span>
<span class="c1"># udev 10240 0 10240 0% /dev</span>
<span class="c1"># tmpfs 37092 4596 32496 13% /run</span>
<span class="hll"><span class="c1"># overlay 92720 1180 91540 2% /</span>
</span><span class="c1"># tmpfs 92720 0 92720 0% /dev/shm</span>
<span class="c1"># tmpfs 5120 4 5116 1% /run/lock</span>
<span class="c1"># tmpfs 92720 0 92720 0% /sys/fs/cgroup</span>
<span class="c1"># /dev/mmcblk0p1 64456 26528 37928 42% /boot</span>
<span class="c1"># tmpfs 18548 0 18548 0% /run/user/1000</span>
</pre></div>
<p>If the filesystem for <tt class="docutils literal">root (/)</tt> shows up as <tt class="docutils literal">overlay</tt> it worked.</p>
Drahtloser Temperatur- und Luftfeuchtesensor mit dem ESP82662015-07-01T21:47:00+02:002015-07-01T21:47:00+02:00ferdinandtag:ferdinandkeil.com,2015-07-01:/drahtloser-temperatur-und-luftfeuchtesensor-mit-dem-esp8266.html<p><img alt="20150629_224111-600" src="https://ferdinandkeil.com/uploads/2015/07/20150629_224111-600.jpg" /></p>
<p>Über den <a class="reference external" href="http://espressif.com/en/products/esp8266/">ESP8266</a> der
chinesischen Firma <a class="reference external" href="http://espressif.com/">Espressif</a> ist ja schon an
<a class="reference external" href="http://hackaday.com/2014/08/26/new-chip-alert-the-esp8266-wifi-module-its-5/">vielen</a>
<a class="reference external" href="http://makezine.com/2015/04/01/esp8266-5-microcontroller-wi-fi-now-arduino-compatible/">Stellen</a>
berichtet worden, aber hier nochmal die Kurzfassung: für ca. 3,-- €
bringen die verschiedenen ESP8266-Platinen einen Mikrocontroller mit
WLAN-Schnittstelle, mehrere MB Flash und diverse Schnittstellen mit. Der
Mikrocontroller kann mit eigenen Programmen beschrieben werden und damit
eigene Projekte …</p><p><img alt="20150629_224111-600" src="https://ferdinandkeil.com/uploads/2015/07/20150629_224111-600.jpg" /></p>
<p>Über den <a class="reference external" href="http://espressif.com/en/products/esp8266/">ESP8266</a> der
chinesischen Firma <a class="reference external" href="http://espressif.com/">Espressif</a> ist ja schon an
<a class="reference external" href="http://hackaday.com/2014/08/26/new-chip-alert-the-esp8266-wifi-module-its-5/">vielen</a>
<a class="reference external" href="http://makezine.com/2015/04/01/esp8266-5-microcontroller-wi-fi-now-arduino-compatible/">Stellen</a>
berichtet worden, aber hier nochmal die Kurzfassung: für ca. 3,-- €
bringen die verschiedenen ESP8266-Platinen einen Mikrocontroller mit
WLAN-Schnittstelle, mehrere MB Flash und diverse Schnittstellen mit. Der
Mikrocontroller kann mit eigenen Programmen beschrieben werden und damit
eigene Projekte an das Internet anbinden.</p>
<p>Ich habe vor Kurzem ein ESP12-Modul mit passender Adapterplatine
geschenkt bekommen. Als ersten Versuch mit diesem neuen Modul habe ich
einen drahtlosen Temperatur- und Luftfeuchtesensor gebaut. Als Sensor
habe ich den günstigen DHT11 verwendet. Dazu noch ein 3,3 V Linearregler
und eine Spannungsquelle - das war's. Das Programm habe ich in Lua
geschrieben und mittels dem genialen
<a class="reference external" href="https://github.com/nodemcu/nodemcu-firmware/">NodeMCU</a> Projekt auf
dem ESP8266 laufen lassen. Dabei habe ich auf Code von <a class="reference external" href="http://www.seeedstudio.com/recipe/232-primary-iot-make-with-nodemcu-gt-esp8266-lt.html">Martin
Han</a>
aufgebaut.</p>
<p>Der Code setzt die dht_lib ein um den Sensor auszulesen. Diese liegt im
<a class="reference external" href="https://github.com/nodemcu/nodemcu-firmware/archive/3430e5f826e44719276d941ac9e6ae095bb748aa.zip">Repository von
NodeMCU</a>
und muss mit auf den ESP8266 hochgeladen werden. Für den Upload des
Programms habe ich ein günstiges <a class="reference external" href="http://www.electrodragon.com/product/cp2102-usb-ttl-uart-module-v2/">USB-zu-seriell
Modul</a>
und den <a class="reference external" href="https://github.com/4refr0nt/ESPlorer">ESPlorer von 4refr0nt</a>
benutzt.</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span>
<span class="normal">44</span>
<span class="normal">45</span>
<span class="normal">46</span>
<span class="normal">47</span>
<span class="normal">48</span>
<span class="normal">49</span>
<span class="normal">50</span>
<span class="normal">51</span>
<span class="normal">52</span>
<span class="normal">53</span>
<span class="normal">54</span>
<span class="normal">55</span>
<span class="normal">56</span>
<span class="normal">57</span>
<span class="normal">58</span>
<span class="normal">59</span>
<span class="normal">60</span>
<span class="normal">61</span>
<span class="normal">62</span>
<span class="normal">63</span>
<span class="normal">64</span>
<span class="normal">65</span>
<span class="normal">66</span>
<span class="normal">67</span>
<span class="normal">68</span>
<span class="normal">69</span>
<span class="normal">70</span>
<span class="normal">71</span>
<span class="normal">72</span>
<span class="normal">73</span>
<span class="normal">74</span>
<span class="normal">75</span>
<span class="normal">76</span>
<span class="normal">77</span>
<span class="normal">78</span>
<span class="normal">79</span>
<span class="normal">80</span>
<span class="normal">81</span>
<span class="normal">82</span>
<span class="normal">83</span>
<span class="normal">84</span>
<span class="normal">85</span>
<span class="normal">86</span>
<span class="normal">87</span>
<span class="normal">88</span>
<span class="normal">89</span>
<span class="normal">90</span>
<span class="normal">91</span>
<span class="normal">92</span>
<span class="normal">93</span>
<span class="normal">94</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1">-- ***************************************************************************</span>
<span class="c1">-- Drahtloser Temperatur- und Luftfeuchtesensor</span>
<span class="c1">--</span>
<span class="c1">-- von Ferdinand Keil</span>
<span class="c1">-- basierend auf Code von Martin Han</span>
<span class="c1">--</span>
<span class="c1">-- Public Domain</span>
<span class="c1">-- ***************************************************************************</span>
<span class="c1">--==================================================================</span>
<span class="c1">-- HTML Template</span>
<span class="c1">--==================================================================</span>
<span class="n">CSS_Sheet</span><span class="o">=</span><span class="s">[[<html></span>
<span class="s"><head></span>
<span class="s"><meta http-equiv="refresh" content="2"></span>
<span class="s"><style type="text/css"></span>
<span class="s">#sensor {</span>
<span class="s"> font-family:"Trebuchet MS", Arial, Helvetica, sans-serif;</span>
<span class="s"> width:800px;</span>
<span class="s"> border-collapse:collapse;</span>
<span class="s">}</span>
<span class="s">#sensor td, #sensor th {</span>
<span class="s"> font-size:1em;</span>
<span class="s"> border:1px solid #98bf21;</span>
<span class="s"> padding:3px 7px 2px 7px;</span>
<span class="s">}</span>
<span class="s">#sensor th {</span>
<span class="s"> font-size:1.1em;</span>
<span class="s"> text-align:left;</span>
<span class="s"> padding-top:5px;</span>
<span class="s"> padding-bottom:4px;</span>
<span class="s"> background-color:#A7C942;</span>
<span class="s"> color:#ffffff;</span>
<span class="s">}</span>
<span class="s">#sensor tr.alt td {</span>
<span class="s"> color:#000000;</span>
<span class="s"> background-color:#EAF2D3;</span>
<span class="s">}</span>
<span class="s"></style></span>
<span class="s"></head></span>
<span class="s"><body></span>
<span class="s"><table id="sensor"></span>
<span class="s"><tr></span>
<span class="s"><th>Input Source</th></span>
<span class="s"><th>Temperature</th></span>
<span class="s"><th>Humidity</th></span>
<span class="s"></tr></span>
<span class="s"><tr></span>
<span class="s"><td>DHT Temp&Humi Sensor</td></span>
<span class="s"><td>]]</span>
<span class="n">CSS_2</span><span class="o">=</span><span class="s">[[ deg C</td></span>
<span class="s"><td>]]</span>
<span class="n">CSS_3</span><span class="o">=</span><span class="s">[[ %</td></span>
<span class="s"></tr></span>
<span class="s"></table></span>
<span class="s"></body></span>
<span class="s"></html></span>
<span class="s">]]</span>
<span class="c1">--==================================================================</span>
<span class="c1">-- Hauptprogramm</span>
<span class="c1">--==================================================================</span>
<span class="n">pin</span> <span class="o">=</span> <span class="mi">4</span> <span class="c1">-- Pin mit dem der DHT11 verbunden ist</span>
<span class="n">wifi</span><span class="p">.</span><span class="n">setmode</span><span class="p">(</span><span class="n">wifi</span><span class="p">.</span><span class="n">STATION</span><span class="p">)</span>
<span class="n">wifi</span><span class="p">.</span><span class="n">sta</span><span class="p">.</span><span class="n">config</span><span class="p">(</span><span class="s2">"SSID"</span><span class="p">,</span><span class="s2">"PASSWORD"</span><span class="p">)</span> <span class="c1">-- WLAN Zugangsdaten</span>
<span class="n">wifi</span><span class="p">.</span><span class="n">sta</span><span class="p">.</span><span class="n">connect</span><span class="p">()</span>
<span class="n">dht</span> <span class="o">=</span> <span class="nb">require</span><span class="p">(</span><span class="s2">"dht_lib"</span><span class="p">)</span>
<span class="n">humi</span> <span class="o">=</span> <span class="s2">"Fehler"</span>
<span class="n">temp</span> <span class="o">=</span> <span class="s2">"Fehler"</span>
<span class="c1">-- Server starten wenn Verbindung steht</span>
<span class="n">tmr</span><span class="p">.</span><span class="n">alarm</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">1000</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span> <span class="kr">function</span><span class="p">()</span>
<span class="kr">if</span> <span class="n">wifi</span><span class="p">.</span><span class="n">sta</span><span class="p">.</span><span class="n">getip</span><span class="p">()</span> <span class="o">~=</span> <span class="kc">nil</span> <span class="kr">then</span>
<span class="n">tmr</span><span class="p">.</span><span class="n">stop</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"NodeMcu's IP Address:"</span><span class="o">..</span><span class="n">wifi</span><span class="p">.</span><span class="n">sta</span><span class="p">.</span><span class="n">getip</span><span class="p">())</span>
<span class="n">srv</span><span class="o">=</span><span class="n">net</span><span class="p">.</span><span class="n">createServer</span><span class="p">(</span><span class="n">net</span><span class="p">.</span><span class="n">TCP</span><span class="p">,</span> <span class="mi">10</span><span class="p">)</span>
<span class="n">srv</span><span class="p">:</span><span class="n">listen</span><span class="p">(</span><span class="mi">80</span><span class="p">,</span><span class="kr">function</span><span class="p">(</span><span class="n">conn</span><span class="p">)</span>
<span class="n">conn</span><span class="p">:</span><span class="n">on</span><span class="p">(</span><span class="s2">"receive"</span><span class="p">,</span><span class="kr">function</span><span class="p">(</span><span class="n">conn</span><span class="p">,</span><span class="n">payload</span><span class="p">)</span>
<span class="n">payload</span> <span class="o">=</span> <span class="kc">nil</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"Got request"</span><span class="p">)</span>
<span class="n">conn</span><span class="p">:</span><span class="n">send</span><span class="p">(</span><span class="s2">"HTTP/1.0 200 OK</span><span class="se">\r\n</span><span class="s2">Server: nodemcu-httpserver</span><span class="se">\r\n</span><span class="s2">Content-Type: text/html</span><span class="se">\r\n</span><span class="s2">Connection: close</span><span class="se">\r\n\r\n</span><span class="s2">"</span><span class="p">)</span>
<span class="n">conn</span><span class="p">:</span><span class="n">send</span><span class="p">(</span><span class="n">CSS_Sheet</span><span class="o">..</span><span class="n">temp</span><span class="o">..</span><span class="n">CSS_2</span><span class="o">..</span><span class="n">humi</span><span class="o">..</span><span class="n">CSS_3</span><span class="p">)</span>
<span class="n">conn</span><span class="p">:</span><span class="n">close</span><span class="p">()</span>
<span class="kr">end</span><span class="p">)</span>
<span class="kr">end</span><span class="p">)</span>
<span class="kr">end</span>
<span class="kr">end</span><span class="p">)</span>
<span class="c1">-- regelmäßig den Sensor abfragen</span>
<span class="n">tmr</span><span class="p">.</span><span class="n">alarm</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">1000</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span> <span class="kr">function</span><span class="p">()</span>
<span class="kr">repeat</span>
<span class="n">dht</span><span class="p">.</span><span class="n">read</span><span class="p">(</span><span class="n">pin</span><span class="p">)</span>
<span class="n">tmr</span><span class="p">.</span><span class="n">wdclr</span><span class="p">()</span>
<span class="kr">until</span> <span class="n">dht</span><span class="p">.</span><span class="n">getHumidity</span><span class="p">()</span> <span class="o">~=</span> <span class="kc">nil</span>
<span class="n">temp</span> <span class="o">=</span> <span class="n">dht</span><span class="p">.</span><span class="n">getTemperature</span><span class="p">()</span><span class="o">/</span><span class="mi">10</span>
<span class="n">humi</span> <span class="o">=</span> <span class="n">dht</span><span class="p">.</span><span class="n">getHumidity</span><span class="p">()</span><span class="o">/</span><span class="mi">10</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"Temperature: "</span><span class="o">..</span><span class="n">temp</span><span class="o">..</span><span class="s2">" deg C, Humidity: "</span><span class="o">..</span><span class="n">humi</span><span class="o">..</span><span class="s2">" %relH"</span><span class="p">)</span>
<span class="kr">end</span><span class="p">)</span>
</pre></div>
</td></tr></table><p>Sobald sich das Modul mit dem WLAN verbunden hat können die Messwerte
über einen Browser angezeigt werden. Dazu muss nur die IP-Adresse die
dem Modul zugewiesen wurde aufgerufen werden. Die Ausgabe sieht dann in
etwa so aus:</p>
<p><img alt="browser_esp8266_dht11-600" src="https://ferdinandkeil.com/uploads/2015/07/browser_esp8266_dht11-600.png" /></p>
AVR Dragon mit avrdude nutzen2015-06-04T23:34:00+02:002015-06-04T23:34:00+02:00ferdinandtag:ferdinandkeil.com,2015-06-04:/avr-dragon-mit-avrdude-nutzen.html<p><img alt="cmd_avrdude" src="https://ferdinandkeil.com/uploads/2015/06/cmd_avrdude.png" /></p>
<p>Um den günstigen <a class="reference external" href="http://www.atmel.com/tools/avrdragon.aspx">AVR Dragon
Programmieradapter</a> von
Atmel mit dem verbreiteten, quelloffenen Tool
<a class="reference external" href="http://www.nongnu.org/avrdude/">avrdude</a> nutzen zu können wird der
libusb-win32 Treiber benötigt. Dieser lässt sich aufgrund der
erforderlichen Signatur nicht ohne weiteres auf modernen Windows
Systemen installieren. Abhilfe schafft hier das Tool
<a class="reference external" href="http://zadig.akeo.ie/">Zadig</a>. Einfach herunterladen, als Treiber
<em>libusb-win32 (v...)</em> auswählen …</p><p><img alt="cmd_avrdude" src="https://ferdinandkeil.com/uploads/2015/06/cmd_avrdude.png" /></p>
<p>Um den günstigen <a class="reference external" href="http://www.atmel.com/tools/avrdragon.aspx">AVR Dragon
Programmieradapter</a> von
Atmel mit dem verbreiteten, quelloffenen Tool
<a class="reference external" href="http://www.nongnu.org/avrdude/">avrdude</a> nutzen zu können wird der
libusb-win32 Treiber benötigt. Dieser lässt sich aufgrund der
erforderlichen Signatur nicht ohne weiteres auf modernen Windows
Systemen installieren. Abhilfe schafft hier das Tool
<a class="reference external" href="http://zadig.akeo.ie/">Zadig</a>. Einfach herunterladen, als Treiber
<em>libusb-win32 (v...)</em> auswählen und auf <em>Install Driver</em> klicken.
Fertig.</p>
<p><img alt="zadig_dialog" src="https://ferdinandkeil.com/uploads/2015/06/zadig_dialog.png" /></p>
Reparatur MBO DIGIMED 2/30 Blutdruckmessgerät2014-08-22T18:37:00+02:002014-08-22T18:37:00+02:00ferdinandtag:ferdinandkeil.com,2014-08-22:/reparatur-mbo-digimed-230-blutdruckmessgeraet.html<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2014/08/mbo_digimed_lcd_defekt.jpg"><img alt="mbo_digimed_lcd_defekt" src="https://ferdinandkeil.com/uploads/2014/08/mbo_digimed_lcd_defekt-300x265.jpg" /></a></p>
<p>Dieser Tage erreichte mich ein defektes Blutdruckmessgerät MBO DIGIMED
2/30. Das LC Display war gestört und zeigte nicht mehr alle Segmente an.
Günstige Consumer Geräte setzen in der Regel maßgeschneiderte LCDs ein
die dann von einem entsprechenden Treiberbaustein oder Mikrocontroller
angesteuert werden. Ist der Kontakt zwischen dem Treiber und …</p><p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2014/08/mbo_digimed_lcd_defekt.jpg"><img alt="mbo_digimed_lcd_defekt" src="https://ferdinandkeil.com/uploads/2014/08/mbo_digimed_lcd_defekt-300x265.jpg" /></a></p>
<p>Dieser Tage erreichte mich ein defektes Blutdruckmessgerät MBO DIGIMED
2/30. Das LC Display war gestört und zeigte nicht mehr alle Segmente an.
Günstige Consumer Geräte setzen in der Regel maßgeschneiderte LCDs ein
die dann von einem entsprechenden Treiberbaustein oder Mikrocontroller
angesteuert werden. Ist der Kontakt zwischen dem Treiber und dem
eigentlichen Display Glas gestört macht sich das durch fehlende Segmente
bemerkbar.</p>
<p>Da das LCD in diesem Gerät nicht durch einen flexibel Kontaktstreifen
(Zebrastrip) kontaktiert wird war es mit Kontakte reinigen und wieder
zusammenbauen nicht getan. Trotzdem konnte ich die Funktion wieder
herstellen.</p>
<p><strong>Diese Anleitung dürfte sich auf ähnliche Geräte ohne Probleme
übertragen lassen.</strong></p>
<div class="section" id="benotigtes-werkzeug">
<h2>Benötigtes Werkzeug:</h2>
<ul class="simple">
<li>Schraubenzieher Philips Größe 0 (PH 0)</li>
<li>Pinzette</li>
<li>Bügeleisen</li>
</ul>
</div>
<div class="section" id="schritt-1">
<h2>Schritt 1</h2>
<p>Zunächst muss das Gerät geöffnet werden. Dazu zuerst die Batterien
entnehmen und die Armmanschette entfernen. Die Manschette wird durch
zwei Schrauben im Batteriefach gehalten.</p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2014/08/mbo_digimed_schrauben_manschette-1.jpg"><img alt="mbo_digimed_schrauben_manschette-1" src="https://ferdinandkeil.com/uploads/2014/08/mbo_digimed_schrauben_manschette-1-300x298.jpg" /></a>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2014/08/mbo_digimed_schrauben_manschette-2.jpg"><img alt="mbo_digimed_schrauben_manschette-2" src="https://ferdinandkeil.com/uploads/2014/08/mbo_digimed_schrauben_manschette-2-300x291.jpg" /></a></p>
<p>Anschließend müssen die zwei Schrauben auf der Rückseite entfernt werden
um diese abnehmen zu können. Die Rückseite wird zusätzlich durch mehrere
Rastnasen gehalten, diese lösen sich durch leichten Druck.</p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2014/08/mbo_digimed_schrauben_rueckseite.jpg"><img alt="mbo_digimed_schrauben_rueckseite" src="https://ferdinandkeil.com/uploads/2014/08/mbo_digimed_schrauben_rueckseite-300x168.jpg" /></a>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2014/08/mbo_digimed_rastnasen_rueckseite.jpg"><img alt="mbo_digimed_rastnasen_rueckseite" src="https://ferdinandkeil.com/uploads/2014/08/mbo_digimed_rastnasen_rueckseite-300x168.jpg" /></a></p>
</div>
<div class="section" id="schritt-2">
<h2>Schritt 2</h2>
<p>Nun muss die Elektronik aus dem Gehäuse entfernt werden. Diese besteht
aus zwei gestapelten Platinen die durch einen Pfostenstecker verbunden
werden. Zunächst sollte das weiße Luftauslassventil und die
Batteriekontakte gelöst werden. Das Ventil wird durch zwei Haken
gehalten. Die Batteriekontakte können mit der Pinzette vorsichtig aus
der Halterung gezogen werden.</p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2014/08/mbo_digimed_elektronik-1.jpg"><img alt="mbo_digimed_elektronik-1" src="https://ferdinandkeil.com/uploads/2014/08/mbo_digimed_elektronik-1-300x287.jpg" /></a></p>
<p>Anschließend die Platine gerade nach oben abziehen. Die untere Platine
ist nun sichtbar. Sie wird durch 4 Schrauben gehalten. Diese lösen und
die Platine vorsichtig entnehmen.</p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2014/08/mbo_digimed_elektronik-2.jpg"><img alt="mbo_digimed_elektronik-2" src="https://ferdinandkeil.com/uploads/2014/08/mbo_digimed_elektronik-2-300x168.jpg" /></a> <a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2014/08/mbo_digimed_elektronik-3.jpg"><img alt="mbo_digimed_elektronik-3" src="https://ferdinandkeil.com/uploads/2014/08/mbo_digimed_elektronik-3-279x300.jpg" /></a></p>
</div>
<div class="section" id="schritt-3">
<h2>Schritt 3</h2>
<p>Auf der Hauptplatine befindet sich eine Art Flachbandkabel. Dieses
schwarz-weiß gestreifte Kabel verbindet das LCD Glas mit dem
Mikrocontroller. Der Fehler bei meinem Gerät lag in den Kontakten vom
Kabel zur Platine. Das Kabel scheint dem Aussehen nach eine
kohlebasierte Leitschicht zu enthalten. Deren Kontakt zur Platine ist im
Laufe der Zeit (durch Luftfeuchtigkeit?) immer schlechter geworden bis
das Display dann ausfiel. Um den Kontakt wieder herzustellen kommt jetzt
das Bügeleisen zum Einsatz. Ich habe das Bügeleisen dazu auf Stufe 1
gestellt und dann die Kontaktstelle auf der Platine mit leichtem Druck
über die Kante der Bügelsohle gezogen. Anschließend das Gerät Testen
(Platinen zusammenstecken, Batteriekontakte einsetzen und anschalten)
und gegebenenfalls die Prozedur wiederholen.</p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2014/08/mbo_digimed_buegeleisen.jpg"><img alt="mbo_digimed_buegeleisen" src="https://ferdinandkeil.com/uploads/2014/08/mbo_digimed_buegeleisen-300x168.jpg" /></a></p>
</div>
<div class="section" id="schritt-4">
<h2>Schritt 4</h2>
<p>Nun muss das Gerät nur wieder zusammengebaut werden. Dazu die Schritte
oben in umgekehrter Reihenfolge durchgehen. Mit etwas Glück und Geschick
hat man danach wieder ein funktionierendes Blutdruckmessgerät.</p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2014/08/mbo_digimed_fertig.jpg"><img alt="mbo_digimed_fertig" src="https://ferdinandkeil.com/uploads/2014/08/mbo_digimed_fertig-269x300.jpg" /></a></p>
</div>
What's inside a cheap TOSLINK, S/PDIF to Cinch adapter2014-03-16T14:56:00+01:002014-03-16T14:56:00+01:00ferdinandtag:ferdinandkeil.com,2014-03-16:/whats-inside-a-cheap-toslink-to-cinch-adapter.html<p><img alt="toslink_dac-600" src="https://ferdinandkeil.com/uploads/2014/03/toslink_dac-600.jpg" /></p>
<p>I wanted to connect my TV to my Hifi system but found it lacking an
analog output. On Amazon.de I stumbled upon this <a class="reference external" href="http://www.amazon.de/CSL-Konverter-Entertainment-Reduction-Vollmetall/dp/B00DS2QBKA/">cheap audio
DAC</a>,
converting a TOSLINK input to line level stereo outputs. About 17 EUR
shipped sounded reasonable to me, so I ordered it right away …</p><p><img alt="toslink_dac-600" src="https://ferdinandkeil.com/uploads/2014/03/toslink_dac-600.jpg" /></p>
<p>I wanted to connect my TV to my Hifi system but found it lacking an
analog output. On Amazon.de I stumbled upon this <a class="reference external" href="http://www.amazon.de/CSL-Konverter-Entertainment-Reduction-Vollmetall/dp/B00DS2QBKA/">cheap audio
DAC</a>,
converting a TOSLINK input to line level stereo outputs. About 17 EUR
shipped sounded reasonable to me, so I ordered it right away. However at
that price (including a wall plug) I was curious what components are
inside this thing. So you know how Dave Jones says, don't turn it on,
turn it apart!</p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2014/03/20140308_222114-1600.jpg"><img alt="20140308_222114-1600" src="https://ferdinandkeil.com/uploads/2014/03/20140308_222114-1600-300x168.jpg" /></a> <a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2014/03/20140308_222003-1600.jpg"><img alt="20140308_222003-1600" src="https://ferdinandkeil.com/uploads/2014/03/20140308_222003-1600-300x168.jpg" /></a></p>
<p>The magic is obviously happening on the bottom side of the board. You
can find a high resolution scan of it below. The main ICs are both
Cirrus Logic parts: the <a class="reference external" href="http://www.cirrus.com/en/products/cs8416.html">CS8416 192 kHz digital audio
receiver</a> and the
<a class="reference external" href="http://www.cirrus.com/en/products/cs4344-45-46-48.html">CS4344 24-bit, 192 kHz stereo
DAC</a>. As
both parts support sample rates up to 192 kHz the device likely
exceeds its spec of 96 kHz. The DAC features a dynamic range of 105 dB
and -90 dB THD+N, which should be good enough for my purposes.
There also is an LDO and some passives. The soldering looks rather
good, at least for the price. The board layout is also reasonable,
analog and digital parts are somewhat separated, the digital lines
going to the DAC have series resistors, the DAC's outputs even got
protection diodes.</p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2014/03/cs4344_spdif_dac_hires.jpg"><img alt="cs4344_spdif_dac_hires" src="https://ferdinandkeil.com/uploads/2014/03/cs4344_spdif_dac_hires-300x196.jpg" /></a></p>
<p>I've used the device for more than a week now and I'm quite pleased with
it's performance. It's compact size makes it easy to hide it behind the
TV. In a next step I'll build a USB-to-barrel-plug adapter to power it
from one of the TV's USB ports. That way it will be turned on and off
together with the TV.</p>
Connect V-USB devices to the Internet with the TL-WR703N – Part 22013-08-07T15:49:00+02:002013-08-07T15:49:00+02:00ferdinandtag:ferdinandkeil.com,2013-08-07:/connect-v-usb-devices-to-the-internet-with-the-tl-wr703n-part-2.html<p>In the first part of this mini-series I established a basic
communication between my device and the TL-WR703N. In this part I will
request data from my device over USB and then push it to
<a class="reference external" href="http://cosm.com">Cosm</a>. Cosm is a service that can store and display
sensor data, which is exactly …</p><p>In the first part of this mini-series I established a basic
communication between my device and the TL-WR703N. In this part I will
request data from my device over USB and then push it to
<a class="reference external" href="http://cosm.com">Cosm</a>. Cosm is a service that can store and display
sensor data, which is exactly what I want to do. <strong>Cosm recently became</strong>
<a class="reference external" href="https://xively.com/">Xively</a> <strong>(the third name-change in the history
of the service...). The good news is, that the old API still works.</strong></p>
<p>You can talk to Cosm over a REST API. I searched the web for a Lua
implementation of this API and finally found <a class="reference external" href="http://forum.micasaverde.com/index.php?topic=7396.0">some code by a guy named
Shadock</a>. To
simplify usage I created a small Lua library:</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1">-- save as 'luacosm.lua'</span>
<span class="c1">-- load libs</span>
<span class="nb">require</span><span class="p">(</span><span class="s2">"ltn12"</span><span class="p">)</span>
<span class="n">socket</span> <span class="o">=</span> <span class="nb">require</span><span class="p">(</span><span class="s2">"socket"</span><span class="p">)</span>
<span class="n">http</span> <span class="o">=</span> <span class="nb">require</span><span class="p">(</span><span class="s2">"socket.http"</span><span class="p">)</span>
<span class="c1">-- cosm_put(apikey, feed, datastream, value)</span>
<span class="c1">-- Push's a value to the specified Cosm feed.</span>
<span class="c1">-- Has to be given an API-Key with the necessary permissions.</span>
<span class="c1">--</span>
<span class="c1">-- based on Shadock's code as published on</span>
<span class="c1">-- http://forum.micasaverde.com/index.php?topic=7396.0</span>
<span class="kr">function</span> <span class="nf">cosm_put</span><span class="p">(</span><span class="n">apikey</span><span class="p">,</span> <span class="n">feed</span><span class="p">,</span> <span class="n">datastream</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
<span class="kd">local</span> <span class="n">base_url</span> <span class="o">=</span> <span class="s2">"http://api.cosm.com/v2/feeds/"</span>
<span class="kd">local</span> <span class="n">method</span> <span class="o">=</span> <span class="s2">"PUT"</span>
<span class="kd">local</span> <span class="n">json_data</span> <span class="o">=</span> <span class="s1">'{ "version":"1.0.0","datastreams":[ {"id":"'</span> <span class="o">..</span> <span class="n">datastream</span> <span class="o">..</span> <span class="s1">'", "current_value":"'</span> <span class="o">..</span> <span class="n">value</span> <span class="o">..</span> <span class="s1">'"}]}'</span>
<span class="kd">local</span> <span class="n">response_body</span> <span class="o">=</span> <span class="p">{}</span>
<span class="kd">local</span> <span class="n">response</span><span class="p">,</span> <span class="n">status</span><span class="p">,</span> <span class="n">header</span> <span class="o">=</span> <span class="n">http</span><span class="p">.</span><span class="n">request</span><span class="p">{</span>
<span class="n">method</span> <span class="o">=</span> <span class="n">method</span><span class="p">,</span>
<span class="n">url</span> <span class="o">=</span> <span class="n">base_url</span> <span class="o">..</span> <span class="n">feed</span> <span class="o">..</span> <span class="s2">".json"</span><span class="p">,</span>
<span class="n">headers</span> <span class="o">=</span> <span class="p">{</span>
<span class="p">[</span><span class="s2">"Content-Type"</span><span class="p">]</span> <span class="o">=</span> <span class="s2">"application/json"</span><span class="p">,</span>
<span class="p">[</span><span class="s2">"Content-Length"</span><span class="p">]</span> <span class="o">=</span> <span class="nb">string.len</span><span class="p">(</span><span class="n">json_data</span><span class="p">),</span>
<span class="p">[</span><span class="s2">"X-ApiKey"</span><span class="p">]</span> <span class="o">=</span> <span class="n">apikey</span>
<span class="p">},</span>
<span class="n">source</span> <span class="o">=</span> <span class="n">ltn12</span><span class="p">.</span><span class="n">source</span><span class="p">.</span><span class="n">string</span><span class="p">(</span><span class="n">json_data</span><span class="p">),</span>
<span class="n">sink</span> <span class="o">=</span> <span class="n">ltn12</span><span class="p">.</span><span class="n">sink</span><span class="p">.</span><span class="n">table</span><span class="p">(</span><span class="n">response_body</span><span class="p">)</span>
<span class="p">}</span>
<span class="kr">return</span> <span class="n">response</span><span class="p">,</span> <span class="n">status</span><span class="p">,</span> <span class="n">header</span>
<span class="kr">end</span>
</pre></div>
</td></tr></table><p>A short example shows how to use the library:</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="nb">require</span><span class="p">(</span><span class="s2">"math"</span><span class="p">)</span>
<span class="nb">require</span><span class="p">(</span><span class="s2">"luacosm"</span><span class="p">)</span>
<span class="kd">local</span> <span class="n">apikey</span> <span class="o">=</span> <span class="s2">"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"</span>
<span class="kd">local</span> <span class="n">feedid</span> <span class="o">=</span> <span class="mi">123456</span>
<span class="nb">math.randomseed</span><span class="p">(</span> <span class="nb">os.time</span><span class="p">()</span> <span class="p">)</span>
<span class="kd">local</span> <span class="n">humidity</span> <span class="o">=</span> <span class="nb">math.random</span><span class="p">(</span><span class="mi">60</span><span class="p">,</span> <span class="mi">80</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"Humidity: "</span> <span class="o">..</span> <span class="n">humidity</span> <span class="o">..</span> <span class="s2">"%relH"</span><span class="p">)</span>
<span class="kd">local</span> <span class="n">response</span><span class="p">,</span> <span class="n">status</span><span class="p">,</span> <span class="n">header</span> <span class="o">=</span> <span class="n">cosm_put</span><span class="p">(</span><span class="n">apikey</span><span class="p">,</span> <span class="n">feedid</span><span class="p">,</span> <span class="s2">"Humidity"</span><span class="p">,</span> <span class="n">humidity</span><span class="p">)</span>
</pre></div>
</td></tr></table><p>To start sending data, you first have to create so called feed in
Cosm. This gives you the feed ID. You also need your personal API key,
which can also be found on the Cosm website. Then all that is left is
pushing some data to your feed.
The code shown above runs on the firmware image Madox generated for
the TL-WR703N. It ships with all necessary Lua libraries, so no need
to compile anything.</p>
<p>After verifying that I can upload random data to Cosm, I still need to
retrieve some real sensor readings from my device. Again I used V-USB
and lualibusb1 to connect my device to the router. I adapted the script
presented in the first part of the series for this purpose.</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="nb">require</span><span class="p">(</span><span class="s2">"luacosm"</span><span class="p">)</span>
<span class="n">usb</span> <span class="o">=</span> <span class="nb">require</span><span class="p">(</span><span class="s2">"libusb1"</span><span class="p">)</span>
<span class="n">PSCMD_STATUS</span> <span class="o">=</span> <span class="mi">1</span>
<span class="n">PSCMD_ON</span> <span class="o">=</span> <span class="mi">2</span>
<span class="n">PSCMD_OFF</span> <span class="o">=</span> <span class="mi">3</span>
<span class="kd">local</span> <span class="n">apikey</span> <span class="o">=</span> <span class="s2">"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"</span>
<span class="kd">local</span> <span class="n">feedid</span> <span class="o">=</span> <span class="mi">123456</span>
<span class="kd">local</span> <span class="n">handle</span> <span class="o">=</span> <span class="n">usb</span><span class="p">.</span><span class="n">open_device_with_vid_pid</span><span class="p">(</span><span class="mh">0x16C0</span><span class="p">,</span> <span class="mh">0x05DC</span><span class="p">);</span>
<span class="kr">if</span> <span class="p">((</span><span class="n">usb</span><span class="p">.</span><span class="n">get_string_descriptor_ascii</span><span class="p">(</span><span class="n">handle</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">~=</span> <span class="s2">"www.ferdinandkeil.com"</span><span class="p">)</span>
<span class="ow">and</span> <span class="p">(</span><span class="n">usb</span><span class="p">.</span><span class="n">get_string_descriptor_ascii</span><span class="p">(</span><span class="n">handle</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> <span class="o">~=</span> <span class="s2">"Humidor Steuerung"</span><span class="p">))</span> <span class="kr">then</span>
<span class="n">handle</span> <span class="o">=</span> <span class="kc">nil</span><span class="p">;</span>
<span class="kr">end</span>
<span class="kr">if</span> <span class="p">(</span><span class="n">handle</span><span class="o">~=</span><span class="kc">nil</span><span class="p">)</span> <span class="kr">then</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"Device successfully initialised!"</span><span class="p">)</span>
<span class="kd">local</span> <span class="nb">type</span> <span class="o">=</span> <span class="n">usb</span><span class="p">.</span><span class="n">LIBUSB_REQUEST_TYPE_VENDOR</span> <span class="o">+</span> <span class="n">usb</span><span class="p">.</span><span class="n">LIBUSB_RECIPIENT_DEVICE</span> <span class="o">+</span> <span class="n">usb</span><span class="p">.</span><span class="n">LIBUSB_ENDPOINT_IN</span>
<span class="kd">local</span> <span class="n">request</span> <span class="o">=</span> <span class="n">PSCMD_STATUS</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"Request data from device..."</span><span class="p">)</span>
<span class="kd">local</span> <span class="n">response</span> <span class="o">=</span> <span class="n">usb</span><span class="p">.</span><span class="n">control_transfer</span><span class="p">(</span><span class="n">handle</span><span class="p">,</span> <span class="nb">type</span><span class="p">,</span> <span class="n">request</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">5000</span><span class="p">)</span>
<span class="kd">local</span> <span class="n">hi</span> <span class="o">=</span> <span class="nb">string.byte</span><span class="p">(</span><span class="n">response</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="kd">local</span> <span class="n">lo</span> <span class="o">=</span> <span class="nb">string.byte</span><span class="p">(</span><span class="n">response</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="kd">local</span> <span class="n">humidity</span> <span class="o">=</span> <span class="p">(</span> <span class="p">(</span><span class="n">hi</span><span class="o">*</span><span class="mi">255</span><span class="p">)</span> <span class="o">+</span> <span class="n">lo</span> <span class="p">)</span> <span class="o">/</span> <span class="mi">100</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"Measured Humidity: "</span> <span class="o">..</span> <span class="n">humidity</span> <span class="o">..</span> <span class="s2">"%relH"</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"Try to upload to Cosm..."</span><span class="p">)</span>
<span class="kd">local</span> <span class="n">response</span><span class="p">,</span> <span class="n">status</span><span class="p">,</span> <span class="n">header</span> <span class="o">=</span> <span class="n">cosm_put</span><span class="p">(</span><span class="n">apikey</span><span class="p">,</span> <span class="n">feedid</span><span class="p">,</span> <span class="s2">"Feuchtigkeit"</span><span class="p">,</span> <span class="n">humidity</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"Finished"</span><span class="p">)</span>
<span class="kr">else</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"Device initialisation failed!"</span><span class="p">)</span>
<span class="kr">end</span>
</pre></div>
</td></tr></table><p>Now let's go through some of the important parts of the code:</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kd">local</span> <span class="n">handle</span> <span class="o">=</span> <span class="n">usb</span><span class="p">.</span><span class="n">open_device_with_vid_pid</span><span class="p">(</span><span class="mh">0x16C0</span><span class="p">,</span> <span class="mh">0x05DC</span><span class="p">);</span>
<span class="kr">if</span> <span class="p">((</span><span class="n">usb</span><span class="p">.</span><span class="n">get_string_descriptor_ascii</span><span class="p">(</span><span class="n">handle</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">~=</span> <span class="s2">"www.ferdinandkeil.com"</span><span class="p">)</span>
<span class="ow">and</span> <span class="p">(</span><span class="n">usb</span><span class="p">.</span><span class="n">get_string_descriptor_ascii</span><span class="p">(</span><span class="n">handle</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> <span class="o">~=</span> <span class="s2">"Humidor Steuerung"</span><span class="p">))</span> <span class="kr">then</span>
<span class="n">handle</span> <span class="o">=</span> <span class="kc">nil</span><span class="p">;</span>
<span class="kr">end</span>
</pre></div>
</td></tr></table><p>I still use the VID/PID supplied by Objective Development, but this time
I tried to honour their license terms. They basically say you can use
their VID/PID freely, but you have to give your device a unique
descriptor. So I ask the device for its descriptor and only accept the
one I have chosen for my device.</p>
<div class="highlight"><pre><span></span><span class="kd">local</span> <span class="n">hi</span> <span class="o">=</span> <span class="nb">string.byte</span><span class="p">(</span><span class="n">response</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="kd">local</span> <span class="n">lo</span> <span class="o">=</span> <span class="nb">string.byte</span><span class="p">(</span><span class="n">response</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="kd">local</span> <span class="n">humidity</span> <span class="o">=</span> <span class="p">(</span> <span class="p">(</span><span class="n">hi</span><span class="o">*</span><span class="mi">255</span><span class="p">)</span> <span class="o">+</span> <span class="n">lo</span> <span class="p">)</span> <span class="o">/</span> <span class="mi">100</span>
</pre></div>
<p>On the micro-controller side the humidity is a 16 bit value, so it is
send as two bytes. On the router side I have to reassemble these two
bytes into one value. That is done with the code shown above.
string.byte(s, i) gives me the raw byte value for the i-th byte in
string s. I then shift the high byte to the left (<tt class="docutils literal">hi*255</tt>) and then
add the low byte.
It took me some time to figure this one out, as I am accustomed to the
way C handles data. But you can't easily typecast variables in Lua, so
you have to use some helper functions. Also there seems to be no shift
operator, so you have to rely on multiplication and division.</p>
Ändern der I2C Adresse eines HYT-131 Sensors2013-04-01T12:23:00+02:002013-04-01T12:23:00+02:00ferdinandtag:ferdinandkeil.com,2013-04-01:/andern-der-i2c-adresse-eines-hyt-131-sensors.html<p>Auf der Suche nach genauen und günstigen Sensoren für meine Humidor
Steuerung bin ich auf den
<a class="reference external" href="http://www.temperaturshop.de/index.php?cat=KAT254&product=HYT131">HYT-131</a>
von B+B Sensors aufmerksam geworden. Für knapp 20 Euro inkl. MwSt.
bekommt man einen maximal ±2,0%relF genauen, kombinierten Temperatur-
und Feuchtigkeitssensor. Das ist deutlich günstiger als der <a class="reference external" href="http://www.sensirion.com/de/produkte/feuchte-temperatur/feuchtesensor-sht15/">Sensirion
SHT15</a>
mit …</p><p>Auf der Suche nach genauen und günstigen Sensoren für meine Humidor
Steuerung bin ich auf den
<a class="reference external" href="http://www.temperaturshop.de/index.php?cat=KAT254&product=HYT131">HYT-131</a>
von B+B Sensors aufmerksam geworden. Für knapp 20 Euro inkl. MwSt.
bekommt man einen maximal ±2,0%relF genauen, kombinierten Temperatur-
und Feuchtigkeitssensor. Das ist deutlich günstiger als der <a class="reference external" href="http://www.sensirion.com/de/produkte/feuchte-temperatur/feuchtesensor-sht15/">Sensirion
SHT15</a>
mit vergleichbaren Werten. Ein weiterer Vorteil des Sensors ist, dass
er über ein Standard I²C-Interface kommuniziert.
Der <a class="reference external" href="http://de.wikipedia.org/wiki/I2c">I²C-Bus</a> unterstützt bis zu
112 Geräte, vorausgesetzt diese haben unterschiedliche Adressen. Das
Datenblatt des HYT-131 erwähnt zwar die Möglichkeit die
voreingestellte Adresse zu ändern, erläutert aber nicht wie. Über
einen <a class="reference external" href="http://www.raspberrypi.org/phpBB3/viewtopic.php?t=31183&p=306104#p306104">Beitrag im Raspberry Pi
Forum</a>
wurde ich dann darauf aufmerksam, dass der HYT-131 genauso wie der
HYT-221 und HYT-271 auf einem IC von ZMDI basieren. Der IC heißt
<a class="reference external" href="http://www.zmdi.com/zssc3122">ZSSC3122</a>, das Datenblatt habe ich
angehängt. Im Datenblatt zu diesem IC finden sich allerhand
Informationen, darunter wie die I²C-Adresse geändert werden kann. Der
Ablauf ist wie folgt:</p>
<ol class="arabic simple">
<li>Sobald der Sensor mit der Versorgungsspannung verbunden wurde muss
innerhalb von 3-10 ms (abhängig von der internen Konfiguration) ein
Befehl gesendet werden um in den <em>Command Mode</em> zu gelangen.</li>
<li>In diesem Modus kann der interne EEPROM beschrieben werden, wobei die
I²C-Adresse im Register <em>Cust_Config</em> hinterlegt ist.</li>
</ol>
<p>Um diesen Vorgang automatisch und zuverlässig durchführen zu können
habe ich eine Arduino Sketch geschrieben. Die bisherige (default 0x28)
und neue Adresse werden über <tt class="docutils literal">defines</tt> angegeben. Der Sensor wird
mit dem Arduino verbunden und dieser mit der Sketch programmiert. Dann
muss nur noch der Serielle Monitor gestartet und ein beliebiges
Zeichen gesendet werden um den Prozess zu starten.
Bei den Sensoren die mir von B+B Sensors geliefert worden sind war das
<em>Comm_lock</em> Flag im Register <em>ZMDI_Config</em> nicht gesetzt. Dadurch
antwortet der Sensor auf allen I²C-Adressen. Die Sketch setzt dieses
Flag, da sonst nicht getestet werden kann ob die Änderung der Adresse
erfolgreich war. Mit der enthaltenen Funktion <tt class="docutils literal"><span class="pre">changeCommLock(...)</span></tt>
kann diese Änderung aber auch wieder rückgängig gemacht werden.</p>
<p><strong>Hinweis:</strong> Falls ein Fehler auftritt ist der Sensor unter Umständen
weder unter seiner alten noch unter der neuen Adresse ansprechbar. In
diesem Fall hilft es den gesamten I²C-Adressraum zu durchlaufen und auf
Geräte zu prüfen.</p>
<p>
<a href="https://ferdinandkeil.com/uploads/2013/04/ZSSC3122_cLite_Data_Sheet_rev_1_30.pdf"><i class="fa fa-file-pdf-o fa-2x" aria-hidden="true"></i> ZSSC3122_cLite_Data_Sheet_rev_1_30.pdf</a>
</p><p>
<a href="https://ferdinandkeil.com/uploads/2013/04/hyt131_i2c_addr_change_release.ino"><i class="fa fa-floppy-o fa-2x" aria-hidden="true"></i> hyt131_i2c_addr_change_release.ino</a>
</p>Connect V-USB devices to the Internet with the TL-WR703N - Part 12013-03-30T17:07:00+01:002013-03-30T17:07:00+01:00ferdinandtag:ferdinandkeil.com,2013-03-30:/connect-v-usb-devices-to-the-internet-with-the-tl-wr703n-part-1.html<p><em>Note: This article is a follow-up to</em> <a class="reference external" href="http://ferdinand-keil.de/2013/01/22/tl-wr703n-as-wifi-client-with-openwrt/">Use the TP-LINK TL-WR703N as a
WiFi client with
OpenWrt</a>.</p>
<p>The reason why I bought the TL-WR703N orignally was to connect my <a class="reference external" href="http://ferdinand-keil.de/2013/03/20/humidor-steuerung-ein-hygrostat-fur-die-zigarrenlagerung/">cigar
humidifier
circuit</a>
to the internet. In the last article I established a WiFi connection to
my local network. Now I …</p><p><em>Note: This article is a follow-up to</em> <a class="reference external" href="http://ferdinand-keil.de/2013/01/22/tl-wr703n-as-wifi-client-with-openwrt/">Use the TP-LINK TL-WR703N as a
WiFi client with
OpenWrt</a>.</p>
<p>The reason why I bought the TL-WR703N orignally was to connect my <a class="reference external" href="http://ferdinand-keil.de/2013/03/20/humidor-steuerung-ein-hygrostat-fur-die-zigarrenlagerung/">cigar
humidifier
circuit</a>
to the internet. In the last article I established a WiFi connection to
my local network. Now I needed a way to talk to my circuit over USB. It
includes a USB port, which I used so far to <a class="reference external" href="http://www.obdev.at/products/vusb/usbasploader.html">update the
firmware</a>. So
all that was left was some firmware based on
<a class="reference external" href="http://www.obdev.at/products/vusb/index-en.html">V-USB</a> and a
script/program on the router side talking to it.</p>
<p>I soon found out, that the easiest way to get talking to USB devices was
using Lua with libusb. However, the original OpenWrt package for the
TL-WR703N doesn't include a libusb binding for Lua. I'm not going to
compile OpenWrt, so... <a class="reference external" href="http://hilariawesome.com/10">to the Googles</a>!
As it happenend to be, <a class="reference external" href="http://www.madox.net/blog/">Madox</a> had
already done all the hard work for me. He posted several <a class="reference external" href="http://www.madox.net/blog/projects/tp-link-tl-wr703n/">firmware
images for the
TL-WR703N</a>, of
which I chose the Standard version. Updating OpenWrt given a proper
firmware image is really easy, so I won't go into detail here.</p>
<p>Now I needed a known-good firmware for my circuit to get started
developing Lua scripts. Objective Development, the people behind V-USB,
developed several example firmwares demonstrating their library. I chose
the
<a class="reference external" href="http://www.obdev.at/products/vusb/powerswitch.html">PowerSwitch</a>, as
it comes with a command-line utility that works under Windows.</p>
<p>I then adapted the firmware for my needs. In the end it would only
toggle one PIN which is connected to an LED. To make sure it's working,
I then connected the device to my PC and ran the command-line utility.
It worked flawlessly first try. Now, I went on to duplicate this
functionality in Lua. The source for the command-line utility is
included with the PowerSwitch example, so I started from that. The
resulting Lua script is shown below. The script does not implement all
functions of the PowerSwitch. It only works on port 0 and can not return
the status of the device.</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1">-- usage: lua powerswitch.lua on|off [duration]</span>
<span class="c1">-- duration (in seconds) is optional</span>
<span class="n">PSCMD_STATUS</span> <span class="o">=</span> <span class="mi">1</span>
<span class="n">PSCMD_ON</span> <span class="o">=</span> <span class="mi">2</span>
<span class="n">PSCMD_OFF</span> <span class="o">=</span> <span class="mi">3</span>
<span class="n">usb</span> <span class="o">=</span> <span class="nb">require</span><span class="p">(</span><span class="s1">'libusb1'</span><span class="p">)</span>
<span class="kd">local</span> <span class="n">handle</span> <span class="o">=</span> <span class="n">usb</span><span class="p">.</span><span class="n">open_device_with_vid_pid</span><span class="p">(</span><span class="mh">0x16C0</span><span class="p">,</span> <span class="mh">0x05DC</span><span class="p">);</span>
<span class="kr">if</span> <span class="p">(</span><span class="n">handle</span><span class="o">~=</span><span class="kc">nil</span><span class="p">)</span> <span class="kr">then</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'Device initialised with success !!'</span><span class="p">)</span>
<span class="kd">local</span> <span class="n">port</span> <span class="o">=</span> <span class="mi">0</span>
<span class="kd">local</span> <span class="n">requesttype</span> <span class="o">=</span> <span class="n">usb</span><span class="p">.</span><span class="n">LIBUSB_REQUEST_TYPE_VENDOR</span> <span class="o">+</span> <span class="n">usb</span><span class="p">.</span><span class="n">LIBUSB_RECIPIENT_DEVICE</span> <span class="o">+</span> <span class="n">usb</span><span class="p">.</span><span class="n">LIBUSB_ENDPOINT_IN</span>
<span class="kd">local</span> <span class="n">request</span> <span class="o">=</span> <span class="n">PSCMD_STATUS</span>
<span class="kr">if</span> <span class="p">(</span><span class="n">arg</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'on'</span><span class="p">)</span> <span class="kr">then</span>
<span class="n">request</span> <span class="o">=</span> <span class="n">PSCMD_ON</span>
<span class="kr">end</span>
<span class="kr">if</span> <span class="p">(</span><span class="n">arg</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'off'</span><span class="p">)</span> <span class="kr">then</span>
<span class="n">request</span> <span class="o">=</span> <span class="n">PSCMD_OFF</span>
<span class="kr">end</span>
<span class="kd">local</span> <span class="n">duration</span> <span class="o">=</span> <span class="mi">0</span>
<span class="kr">if</span> <span class="p">(</span><span class="n">arg</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">~=</span> <span class="kc">nil</span><span class="p">)</span> <span class="kr">then</span>
<span class="n">duration</span> <span class="o">=</span> <span class="n">arg</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">*</span> <span class="mi">5</span>
<span class="kr">end</span>
<span class="n">usb</span><span class="p">.</span><span class="n">control_transfer</span><span class="p">(</span><span class="n">handle</span><span class="p">,</span> <span class="n">requesttype</span><span class="p">,</span> <span class="n">request</span><span class="p">,</span> <span class="n">duration</span><span class="p">,</span> <span class="n">port</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">5000</span><span class="p">)</span>
<span class="kr">else</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'Device initialisation failed !!'</span><span class="p">)</span>
<span class="kr">end</span>
</pre></div>
</td></tr></table><p>There is not much documentation available on how to use libusb with Lua.
I first looked at the <a class="reference external" href="http://wiki.pinguino.cc/index.php/Interfacing_with_Lua">Interfacing with Lua
tutorial</a> for
the Pinguino, but soon found out it was written for a different libusb
binding. The binding for Lua included in Madox's package is
<a class="reference external" href="http://code.google.com/p/lualibusb1/">lualibusb1</a>, for which a
<a class="reference external" href="http://code.google.com/p/lualibusb1/wiki/FunctionReference">function
reference</a>
is available. Some important things to know about lualibusb1 are:</p>
<ul class="simple">
<li><em>open_device_with_vid_pid([ctx, ] vendorid, productid)</em> is
implemented, which makes finding the right device really easy.</li>
<li>When requiring the library, type <em>usb = require('libusb1')</em> and
then work with the object <em>usb</em>.</li>
<li>Constants from libusb are available, but some have different names.
All are prefixed with <em>LIBUSB_</em>, but I still had to look up the
names in the <a class="reference external" href="http://code.google.com/p/lualibusb1/source/browse/trunk/lusb.c?r=15">source of
lualibusb1</a>.</li>
</ul>
<p>One important thing I almost forgot to mention: it is not possible to
hook up a V-USB device directly to a TL-WR703N. That is because <a class="reference external" href="http://wiki.openwrt.org/toh/tp-link/tl-wr703n#usb.port.and.monitoring.serial.console.via.usb-serial">the
TL-WR703N only supports USB2.0 or high-speed
devices</a>.
So the V-USB device has to be connected to a USB hub, which is in turn
connected to the router. Any cheap USB2.0 hub will do, I used this one:
<a class="reference external" href="http://www.reichelt.de/USB-Hubs/LOGILINK-UA0136/3//index.html?ACTION=3&GROUPID=4831&ARTICLE=125047&SHOW=1&START=0&OFFSET=16&">LOGILINK
UA0136</a>.</p>
Adding Lua support to SyntaxHighlighter Evolved2013-03-30T16:28:00+01:002013-03-30T16:28:00+01:00ferdinandtag:ferdinandkeil.com,2013-03-30:/adding-lua-support-to-syntaxhighlighter-evolved.html<p>Following the tutorial on <a class="reference external" href="http://www.viper007bond.com/wordpress-plugins/syntaxhighlighter/adding-a-new-brush-language/">adding a new language to the
SyntaxHighlighter Evolved
Plugin</a>
for WordPress, I generated a plugin for the
<a class="reference external" href="http://en.wikipedia.org/wiki/Lua_%28programming_language%29">Lua</a>
language. The SyntaxHighlighter brush I used was created by <a class="reference external" href="http://www.nekothink.com">HyukYi,
Kwon</a>.
The plugin can be installed through the WordPress admin panel.</p>
<p>
<a href="https://ferdinandkeil.com/uploads/2013/03/syntaxhighlighter-brush-lua.zip"><i class="fa fa-floppy-o fa-2x" aria-hidden="true"></i> syntaxhighlighter-brush-lua.zip</a>
</p>Humidor Steuerung - ein Hygrostat für die Zigarrenlagerung2013-03-20T15:47:00+01:002013-03-20T15:47:00+01:00ferdinandtag:ferdinandkeil.com,2013-03-20:/humidor-steuerung-ein-hygrostat-fur-die-zigarrenlagerung.html<p>Vor mittlerweile fast drei Jahren habe ich auf dieser Seite die
Schaltung für meinen <a class="reference external" href="http://ferdinand-keil.de/elektronik-projekte/humidor-lufter/">Humidor
Lüfter</a>
veröffentlicht. Die Schaltung entstand aus der Idee, die Luft im Humidor
regelmäßig umzuwälzen um eine möglichst gleichmäßige
Feuchtigkeitsverteilung zu erreichen. Die Schaltung funktioniert bis
heute ohne Probleme - nachdem ich sie um eine Batterieüberwachung
erweitert …</p><p>Vor mittlerweile fast drei Jahren habe ich auf dieser Seite die
Schaltung für meinen <a class="reference external" href="http://ferdinand-keil.de/elektronik-projekte/humidor-lufter/">Humidor
Lüfter</a>
veröffentlicht. Die Schaltung entstand aus der Idee, die Luft im Humidor
regelmäßig umzuwälzen um eine möglichst gleichmäßige
Feuchtigkeitsverteilung zu erreichen. Die Schaltung funktioniert bis
heute ohne Probleme - nachdem ich sie um eine Batterieüberwachung
erweitert habe macht sie auch keine Akkus mehr kaputt. Aus der gleichen
Zeit stammte die Idee ein digitales Hygrometer für die Zigarrenlagerung
zu entwerfen.</p>
<div class="figure">
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2012/07/IMG_0016-1600.jpg"><img alt="" src="https://ferdinandkeil.com/uploads/2012/07/IMG_0016-1600-300x225.jpg" /></a>
<p class="caption">Die erste Version der Humidor Steuerung</p>
</div>
<p>Die Idee blieb in der Planungsphase stecken, bis ich mir Anfang 2012
endlich einen Ruck gab das Ganze umzusetzen (auch bedingt durch den
Fund passender LC-Displays in meiner Teile-Kiste). Daraus entstand die
erste Version der Humidor Steuerung. Bei <a class="reference external" href="http://www.mikrocontroller.net/topic/245590">Jakob Kleinen's
Sammelbestellung im mikrocontroller.net
Forum</a> ließ ich zwei
Platinen fertigen und baute sie anschließend auf. Bis auf einen
kleinen Fehler bei der Beschaltung des Drehgebers lief die Steuerung
ohne Problem. Aus einem Testprogramm entwickelte sich die Firmware mit
allen nötigen Features. Meine Ergebnisse veröffentlichte ich im
<a class="reference external" href="http://www.zigarrenforum-online.de/">Zigarrenforum</a>. Die positiven
Kommentare dort ermutigten mich schließlich eine zweite, verbesserte
Version zu entwerfen. Die möchte ich nun hier vorstellen.</p>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2013/03/humidor_controller_top.png"><img alt="" src="https://ferdinandkeil.com/uploads/2013/03/humidor_controller_top-300x165.png" /></a>
<div class="figure">
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2013/01/20121028_215039-e1359209549155.jpg"><img alt="" src="https://ferdinandkeil.com/uploads/2013/01/20121028_215039-e1359209549155-300x210.jpg" /></a>
<p class="caption">Die neue, verbesserte Version</p>
</div>
<p>Die Steuerung ist letztlich ein Hygrostat mit integrierter
Zeitschaltuhr um handelsübliche PC-Lüfter anzusteuern. Insgesamt
stehen vier Lüfter-Kanäle zur Verfügung die unabhängig voneinander
programmiert werden können. An den Sensor Anschluss können
verschiedene Sensor-Typen angeschlossen werden, die Firmware erkennt
den richtigen Typ dann automatisch. Nicht auf dem Bild zu sehen (weil
auf der Rückseite) ist ein Summer, der bei unterschreiten einer
eingestellten Feuchtigkeit Alarm gibt. Außerdem ist eine Alarm-LED
integriert, die durch das Loch über dem Glock-Symbol scheint.</p>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2013/03/humidor_controller_v35_sch.png"><img alt="" src="https://ferdinandkeil.com/uploads/2013/03/humidor_controller_v35_sch-300x205.png" /></a>
<div class="figure">
<img alt="" src="https://ferdinandkeil.com/uploads/2013/03/detail_luefter_kanal.png" />
<p class="caption">Schaltplan und Beschaltung eines Lüfter-Kanals</p>
</div>
<p>Die Lüfter-Kanäle sind alle identisch aufgebaut. Der Summer ist an die
12V Versorgungsspannung angeschlossen und wird ähnlich wie die Lüfter
geschaltet. Jeder Kanal verfügt über einen N-Kanal Schalt-MOSFET im
SOT-23 Package. Mögliche Typen sind z.B. der IRLML2502 oder GF2304.
Jeder Kanal kann mit mindestens 500mA belastet werden, damit kann die
Schaltung nahezu alle erhältlichen Lüfter betreiben.
Zum Schutz des MOSFETs und zur Entstörung der Schaltung sind dem
Lüfter eine Schutzdiode und eine Kondensator parallel geschaltet.</p>
<p>Die Steuerung kann über USB mit einer neuen Firmware geflasht werden.
Dazu wurde der verbaute ATmega168 mit dem
<a class="reference external" href="http://www.obdev.at/products/vusb/usbasploader.html">USBaspLoader</a>
programmiert. Um den Bootloader zu aktivieren muss der Drehgeber
gedrückt werden wenn die Schaltung mit der Spannungsversorgung verbunden
wird.</p>
<p>Die fertige Schaltung sitzt in einem
<a class="reference external" href="http://www.teko.it/de/prodotti/famiglia/TC/serie/100">Standard-Gehäuse</a>
wie eine Frontplatte. Es muss nur ein Loch für die Hohlstecker-Buchse
gebohrt werden, die auf der Rückseite der Platine angeschlossen wird.</p>
<p>Das verwendete Display
<a class="reference external" href="http://www.pollin.de/shop/dt/NDU0OTc4OTk-/Bauelemente_Bauteile/Aktive_Bauelemente/Displays/LCD_Modul_HMC16223SG.html">HMC16223SG</a>
ist leider nicht mehr erhältlich. Aufgrund seiner kleinen Abmessungen
ist es perfekt für ein kompaktes Gerät geeignet. Einen adäquaten Ersatz
konnte ich bisher nicht finden, die nächste Version wird wohl ein
anderes Display verwenden.</p>
<p>Die Firmware für die Steuerung basiert auf meinem
<a class="reference external" href="http://ferdinand-keil.de/2012/11/03/simple-task-scheduler-for-microcontrollers/">Taskmanager</a>.
Sie ist so weit wie möglich modular aufgebaut. Es wurde auch ein
Menü-System verwendet, das auf dem Code des <a class="reference external" href="http://www.siwawi.arubi.uni-kl.de/avr_projects/#bf_app.">Butterfly
GCC-Ports</a>
aufbaut.
Die Firmware um Funktionen für weitere Lüfterkanäle oder mehrere
Sensoren zu erweitern, sollte kein Problem sein. Die aktuelle Firmware
verbraucht ~10,5kB Flash, der Bootloader 4kB - es ist also noch Platz
für Erweiterungen. Alternativ kann ein ATmega328 verbaut werden.</p>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2013/03/sensor_board_v10.png"><img alt="" src="https://ferdinandkeil.com/uploads/2013/03/sensor_board_v10-300x165.png" /></a>
<div class="figure">
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2013/03/20130320_133231-1600.jpg"><img alt="" src="https://ferdinandkeil.com/uploads/2013/03/20130320_133231-1600-300x165.jpg" /></a>
<p class="caption">Die Sensor-Platine: als 3D-Modell und fertig aufgebaut</p>
</div>
<p>Die Sensor-Platine ist mit folgenden Sensoren kompatibel:</p>
<ul class="simple">
<li><a class="reference external" href="http://www.mikrocontroller.net/topic/93362">FOST02 von HopeRF</a>
<em>(nicht mehr erhältlich)</em></li>
<li><a class="reference external" href="http://www.temperaturshop.de/index.php?cat=KAT254&product=HYT131">HYT-131 von B+B
Sensors</a></li>
<li><a class="reference external" href="http://www.sensirion.com/de/produkte/feuchte-temperatur/feuchtesensor-sht15/">SHT10 bis SHT15 von
Sensirion</a></li>
<li><a class="reference external" href="http://www.mikrocontroller.net/part/DHT11">DHT11 von diversen
Herstellern</a> <em>(noch
nicht implementiert)</em></li>
</ul>
<p>Die Sensor-Platine wird mit 12V versorgt und hat einen lokalen
Spannungsregler (<a class="reference external" href="http://www.ti.com/product/lp2980-n">LP2980-N</a>), um
Spannungsverluste über die Zuleitung sowie Störungen zu reduzieren.</p>
<div class="section" id="downloads">
<h2>Downloads</h2>
<p>Die Firmware steht unter <a class="reference external" href="https://github.com/ferdinandkeil/humidor-steuerung/blob/master/LICENSE">MIT
Lizenz</a>,
die Hardware Quelldateien unter der <a class="reference external" href="https://github.com/ferdinandkeil/humidor-steuerung-hw/blob/master/LICENSE">TAPR
Lizenz</a>.
Die Dateien sind hier zu finden:</p>
<p>
<a href="https://github.com/ferdinandkeil/humidor-steuerung"><i class="fa fa-github fa-2x" aria-hidden="true"></i> Firmware Quellcode</a>
</p><p>
<a href="https://github.com/ferdinandkeil/humidor-steuerung"><i class="fa fa-github fa-2x" aria-hidden="true"></i> Hardware EAGLE 6 Dateien</a>
</p></div>
Reparatur eines elektronischen Halogen-Trafos2013-02-28T21:10:00+01:002013-02-28T21:10:00+01:00ferdinandtag:ferdinandkeil.com,2013-02-28:/reparatur-eines-elektronischen-halogen-trafos.html<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2013/02/20130228_152758-1600.jpg"><img alt="20130228_152758-1600" src="https://ferdinandkeil.com/uploads/2013/02/20130228_152758-1600-300x225.jpg" /></a></p>
<p>Dieser elektronische Trafo (Modell EST 105/12.381 von Vossloh-Schwabe)
zeigte seit kurzem ein merkwürdiges Verhalten: nach dem Einschalten
leuchtete die Lampe eine Zeit lang ganz normal, begann dann zu flackern
und erlosch schließlich. War die Lampe ein paar Minuten ausgeschaltet
leuchtete sie wieder und das Spiel begann von vorne …</p><p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2013/02/20130228_152758-1600.jpg"><img alt="20130228_152758-1600" src="https://ferdinandkeil.com/uploads/2013/02/20130228_152758-1600-300x225.jpg" /></a></p>
<p>Dieser elektronische Trafo (Modell EST 105/12.381 von Vossloh-Schwabe)
zeigte seit kurzem ein merkwürdiges Verhalten: nach dem Einschalten
leuchtete die Lampe eine Zeit lang ganz normal, begann dann zu flackern
und erlosch schließlich. War die Lampe ein paar Minuten ausgeschaltet
leuchtete sie wieder und das Spiel begann von vorne. Wo war das Problem?
Die üblichen Verdächtigen waren der Dimmer und eben der Trafo.</p>
<p>Also den Trafo aus der Lampe ausgebaut und aufgemacht. Auf den ersten
Blick sah alles normal aus, keine beschädigten Komponenten oder
durchgeschmorte Leiterbahnen. Die Schaltung machte einen soliden
Eindruck, alle Bauteile sind hochwertig und dürften auch die erhöhten
Temperaturen im Trafo verkraften. Aber beim zweiten Blick sah ich es:
eine Lötstelle am Transformator L3 (auf der Sekundär-Seite) war
beschädigt. Wahrscheinlich war die Lötstelle gebrochen (evtl. eine kalte
Lötstelle) und die im Betrieb fließenden Ströme haben dann das Lot rund
um das Bauteil-Beinchen in Rauch aufgehen lassen. Dass die Lampe
überhaupt funktionierte lag letztlich daran, dass sich die Lötstelle
erst durch die im Betrieb auftretende Wärme ausdehnte und so den Kontakt
unterbrach.</p>
<p>Eine kurze Behandlung mit dem Lötkolben später und der Trafo läuft
wieder ohne Probleme.</p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2013/02/20130228_152816-1600.jpg"><img alt="20130228_152816-1600" src="https://ferdinandkeil.com/uploads/2013/02/20130228_152816-1600-150x150.jpg" /></a> <a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2013/02/20130228_152949-1600.jpg"><img alt="20130228_152949-1600" src="https://ferdinandkeil.com/uploads/2013/02/20130228_152949-1600-150x150.jpg" /></a> <a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2013/02/20130228_153540-1600.jpg"><img alt="20130228_153540-1600" src="https://ferdinandkeil.com/uploads/2013/02/20130228_153540-1600-150x150.jpg" /></a>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2013/02/20130228_153721-1600.jpg"><img alt="20130228_153721-1600" src="https://ferdinandkeil.com/uploads/2013/02/20130228_153721-1600-150x150.jpg" /></a></p>
Use the TP-LINK TL-WR703N as a WiFi client with OpenWrt2013-01-22T19:10:00+01:002013-01-22T19:10:00+01:00ferdinandtag:ferdinandkeil.com,2013-01-22:/tl-wr703n-as-wifi-client-with-openwrt.html<p>I recently bought a TP-Link TL-WR703N router on eBay to connect one of
my projects to the net. The router arrived today, just 18 days after I
ordered it from China. I need it to operate as a client in my wireless
network, so after I successfully installed OpenWrt I …</p><p>I recently bought a TP-Link TL-WR703N router on eBay to connect one of
my projects to the net. The router arrived today, just 18 days after I
ordered it from China. I need it to operate as a client in my wireless
network, so after I successfully installed OpenWrt I had to configure it
accordingly. These are the steps I followed:</p>
<p><strong>Warning:
Don't follow these steps if you're not familiar with OpenWrt or Linux.
These instructions are provided "as is", without warranty of any
kind.</strong></p>
<p><strong>Step 1: Install OpenWrt</strong></p>
<p>Download the <a class="reference external" href="http://downloads.openwrt.org/attitude_adjustment/12.09-beta/ar71xx/generic/openwrt-ar71xx-generic-tl-wr703n-v1-squashfs-factory.bin">latest
firmware</a>
for the TL-WR703N. To install it, connect the router to your PC via
wired network. The (Chinese) admin interface is available at
192.168.1.1, so configure you network settings accordingly.
To flash OpenWrt first rename the downloaded file to openwrt.bin (the
router seems to have problems with long file-names). Then login to the
admin interface (username: admin, password: admin) and select the last
menu item in the row to the left (but not the one below), then the
third sub-menu item. Click on the button right to the text-field and
select the firmware file. Click on the button in the bottom left
corner and wait till the router reboots (LED is off, then flashing
while reboot).</p>
<p>Source: <a class="reference external" href="http://wiki.openwrt.org/toh/tp-link/tl-wr703n#flashing">OpenWrt Wiki - TP-Link TL-WR703N -
Flashing</a></p>
<p><strong>Step 2: Configure the IP-Address</strong></p>
<p>When the router finished rebooting open the OpenWrt admin interface in
your browser (again at 192.168.1.1). To ease the further steps we will
now change the default IP address of the router. Go to <em>Network -
Interfaces - LAN</em> and click "Edit". Change "IPv4 address" to one that
lies in the subnet your (main) router is in. Then change "IPv4
address" and "Use custom DNS servers" to your (main) router's IP
address. Check "Ignore interface" and save and apply the settings.
Then go to <em>Network - Interfaces - WAN</em> and click "Edit". Check
"Ignore interface" and save and apply the settings.
You still have to set a password for OpenWrt. Do that by clicking on
the link shown in the red warning. Enter a password, repeat it and
save and apply it.
Then go to <em>Network - DNCP and DNS - General Settings</em>, set "DNS
forwardings" to your (main) router's IP address and save and apply.
Now connect the TL-WR703N to your (main) router via wired network.</p>
<p><strong>Step 3: Install packets and configure network settings</strong></p>
<p>Point your browser to the IP address you've given to the TL-WR703N (if
that does not work, power-cycle the router). Then go to <em>System -
Software</em> and click on "Update lists". Now install the following
packets: <em>relayd</em>, <em>luci-proto-relay</em> and <em>joe</em>. To install them,
enter their name into the text-field labelled "Download and install
package" and click on "OK".
Now open
<a class="reference external" href="http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html">PuTTY</a>
and point it to the router's address. Login and type</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span> /etc/config/ joe network
</pre></div>
<p>and change the file, so it looks like this:</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span>config interface 'loopback'
option ifname 'lo'
option proto 'static'
option ipaddr '127.0.0.1'
option netmask '255.0.0.0'``
config interface 'lan'
option ifname 'eth0'
option type 'bridge'
option proto 'static'
option netmask '255.255.255.0'
option ipaddr '192.168.1.1'
option gateway '192.168.2.1'
option dns '192.168.2.1'
config interface 'wwan'
option _orig_ifname 'radio0.network1'
option _orig_bridge 'false'
option proto 'static'
option ipaddr '192.168.2.200'
option netmask '255.255.255.0'
option gateway '192.168.2.1'
option dns '192.168.2.1'
config interface 'stabridge'
option proto 'relay'
option ipaddr '192.168.2.201'
list network 'lan'
list network 'wwan'
</pre></div>
</td></tr></table><p>Notice:</p>
<ul class="simple">
<li>The IP-address under <em>lan - ipaddr</em> <strong>must not</strong> be in the same
subnet as your (main) router.</li>
<li>The IP-addresses under <em>wwan - ipaddr</em> and <em>stabridge - ipaddr</em> must
be in the same subnet as your (main) router.</li>
<li>The IP-addresses under <em>wwan - gateway</em> and <em>wwan - dns</em> must be your
(main) router's IP-adress.</li>
</ul>
<p>Save the changes and exit joe by pressing <em>Ctrl-K</em> and <em>X</em>. Then enter</p>
<div class="highlight"><pre><span></span>joe wireless
</pre></div>
<p>and change the file so it looks like this:</p>
<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span>config wifi-device 'radio0'
option type 'mac80211'
option macaddr '00:00:00:00:00:00'
option hwmode '11ng'
option htmode 'HT20'
list ht_capab 'SHORT-GI-20'
list ht_capab 'SHORT-GI-40'
list ht_capab 'RX-STBC1'
list ht_capab 'DSSS_CCK-40'
option disabled '0'
option channel '1'
config wifi-iface
option network 'wwan'
option ssid 'YOUR-SSID'
option encryption 'psk2'
option device 'radio0'
option mode 'sta'
option key 'YOUR-PSK-KEY'
</pre></div>
</td></tr></table><p>Notice:</p>
<ul class="simple">
<li><strong>Don't change *radio0 - macaddr*!</strong></li>
<li>YOUR-SSID has to be your (main) router's wireless SSID, YOUR-PSK-KEY
the passphrase for the network.</li>
</ul>
<p>Again, save the changes and exit joe by pressing <em>Ctrl-K</em> and <em>X</em>. Close
the SSH connection by typing "exit".</p>
<p>Now disconnect the network cable and power-cycle the router. It should
now be available through its wireless connection. Check it by entering
the IP you've given to it in the browser. If you have problems, you can
connect the device to your PC and point your browser to the address
you've given to the "LAN" interface (configure your local LAN settings
accordingly). If everything else fails, you can enter the failsafe mode
by following the steps in the <a class="reference external" href="http://wiki.openwrt.org/toh/tp-link/tl-wr703n#failsafe.mode">OpenWrt
wiki</a>.</p>
<p>Source: <a class="reference external" href="https://forum.openwrt.org/viewtopic.php?pid=173467#p173467">OpenWrt Forum - TP-Link TL-WR703N - how to configure it as a
wirelesss
client</a></p>
<p><strong>Step 4: Install the Bootstrap theme (optional)</strong></p>
<p>I don't like the default theme OpenWrt uses for the admin interface.
<a class="reference external" href="http://nut-bolt.nl">David Menting</a>, a Dutch industrial designer has
created a nice alternative called the <a class="reference external" href="http://nut-bolt.nl/2012/openwrt-bootstrap-theme-for-luci/">OpenWrt Bootstrap
theme</a>.
Built upon Twitter's Bootstrap framework it offers a much more
up-to-date look and feel. To install it, connect to your TL-WR703N via
PuTTY. Then enter the following commands:</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span> /tmp
wget http://nut-bolt.nl/files/luci-theme-bootstrap_1-1_all.ipk
opkg install luci-theme-bootstrap_1-1_all.ipk
</pre></div>
<p>Now you can select the theme in the admin interface. Go to <em>System -
System - Language and Style</em> and select "Bootstrap" from the dropdown
menu labelled "Design". Apply and save, click any link and enjoy the
warm, fuzzy feeling of a modern web-application :)
Although this step is optional I still highly recommend it.</p>
Simple Task Scheduler for Microcontrollers2012-11-03T16:19:00+01:002012-11-03T16:19:00+01:00ferdinandtag:ferdinandkeil.com,2012-11-03:/simple-task-scheduler-for-microcontrollers.html<img alt="" src="https://ferdinandkeil.com/uploads/2012/11/task_scheduler_code.png" />
<p>For a project I'm currently working on I need to write a (at least for
me) fairly complex firmware. The code I used in the last version of
this circuit grew out of a test program and became unmaintainable. So
I looked around for some inspiration and found Alan Burlison's …</p><img alt="" src="https://ferdinandkeil.com/uploads/2012/11/task_scheduler_code.png" />
<p>For a project I'm currently working on I need to write a (at least for
me) fairly complex firmware. The code I used in the last version of
this circuit grew out of a test program and became unmaintainable. So
I looked around for some inspiration and found Alan Burlison's
<a class="reference external" href="http://bleaklow.com/2010/07/20/a_very_simple_arduino_task_manager.html">Arduino task
manager</a>.
It's a great piece of code, so I wanted to give it a try. One problem
remained: his code is for the Arduino, but I use plain C with avr-gcc.
So I adapted his code for my use.
While trying to convert his code to C I found one flaw. His
implementation of timed tasks doesn't handle timer roll-overs
gracefully. As my circuit is supposed to run for months without reset,
that was out of the question. Finally I found a solution by Bombastic
Bob on <a class="reference external" href="http://www.arduino.cc/playground/Code/TimingRollover">Arduino
Playground</a>.
Now it works like a charm. I attached my code, you are free to use it
for your projects. The included example is for an ATmega168 with a
12MHz crystal and an LED on PD6. But I see no reason why this code
can't be used with other micro-controllers as well.</p>
<p>
<a href="https://ferdinandkeil.com/uploads/2012/11/TaskScheduler.zip"><i class="fa fa-floppy-o fa-2x" aria-hidden="true"></i> TaskScheduler.zip</a>
</p>Teardown of a cheap rotary encoder2012-09-05T19:00:00+02:002012-09-05T19:00:00+02:00ferdinandtag:ferdinandkeil.com,2012-09-05:/teardown-of-a-cheap-rotary-ecoder.html<p>For my humidor controller project I recently ordered cheap Chinese
rotary encoders via eBay. Before I used the <a class="reference external" href="http://www.pollin.de/shop/dt/NjE2OTU3OTk-/Bauelemente_Bauteile/Passive_Bauelemente/Potis_Trimmer_Encoder/Encoder_Noble_RE0124PVB17_7FINB_24.html">Noble
RE0124PVB17</a>,
but they were out of stock just as I needed more. As I didn't want to
spend much more than 50ct per piece I had to turn eBay for cheap …</p><p>For my humidor controller project I recently ordered cheap Chinese
rotary encoders via eBay. Before I used the <a class="reference external" href="http://www.pollin.de/shop/dt/NjE2OTU3OTk-/Bauelemente_Bauteile/Passive_Bauelemente/Potis_Trimmer_Encoder/Encoder_Noble_RE0124PVB17_7FINB_24.html">Noble
RE0124PVB17</a>,
but they were out of stock just as I needed more. As I didn't want to
spend much more than 50ct per piece I had to turn eBay for cheap
Chinese parts. I paid 6,88 € for 10 pcs incl. shipping and ordered two
bags. The parts arrived just eight days later, which is phenomenal
considering that they were sent from China.
Quality-wise these parts are not on par with the ones from Noble or
Alps. The push-button is ok, but I don't like how they turn. The
detents feel rather unprecise and wiggly. However, they seem to work
and the inner construction is reasonable. I added some pictures of a
unit I tore down. Future will tell if they can stand the expected
usage.</p>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2012/09/IMG_0844-1600.jpg"><img alt="" src="https://ferdinandkeil.com/uploads/2012/09/IMG_0844-1600-300x225.jpg" /></a>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2012/09/IMG_0847-1600.jpg"><img alt="" src="https://ferdinandkeil.com/uploads/2012/09/IMG_0847-1600-300x225.jpg" /></a>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2012/09/IMG_0852-1600.jpg"><img alt="" src="https://ferdinandkeil.com/uploads/2012/09/IMG_0852-1600-300x225.jpg" /></a>
AVR-Transistortester - Downloads2012-05-04T18:45:00+02:002012-05-04T18:45:00+02:00ferdinandtag:ferdinandkeil.com,2012-05-04:/avr-transistortester-downloads.html<img alt="" src="https://ferdinandkeil.com/uploads/2012/04/IMG_0039-1600-300x225.jpg" />
<p>Im Anhang zu diesem Post finden sich die Eagle Quelldateien für die
Schaltung sowie eine angepasste Version des Quellcodes. Da die
Schaltung in einigen Punkten von der Originalversion abweicht kann die
Firmware nicht direkt übernommen werden. Außerdem sollten die in der
Datei fuses.bat voreingestellten Fuse Werte übernommen werden um …</p><img alt="" src="https://ferdinandkeil.com/uploads/2012/04/IMG_0039-1600-300x225.jpg" />
<p>Im Anhang zu diesem Post finden sich die Eagle Quelldateien für die
Schaltung sowie eine angepasste Version des Quellcodes. Da die
Schaltung in einigen Punkten von der Originalversion abweicht kann die
Firmware nicht direkt übernommen werden. Außerdem sollten die in der
Datei fuses.bat voreingestellten Fuse Werte übernommen werden um einen
fehlerfreien Betrieb zu gewährleisten.
Im Archiv Transistortester.zip befindet sich neben den Eagle Dateien
auch eine Teileliste mit Bestellnummern für Reichelt, Mouser und
Farnell. Der Fehler aus der ersten Revision der Platine ist bei den
angehängten Dateien beseitigt, allerdings habe ich diese Version nicht
getestet. Die Schaltung und das Platinenlayout stelle ich unter
<a class="reference external" href="http://creativecommons.org/licenses/by-sa/2.0/de/">CC-BY-SA
Lizenz</a> zur
Verfügung.</p>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2012/05/transistortester_v13_sch.png"><img alt="" src="https://ferdinandkeil.com/uploads/2012/05/transistortester_v13_sch-300x205.png" /></a>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2012/05/transistortester_v13_brd.png"><img alt="" src="https://ferdinandkeil.com/uploads/2012/05/transistortester_v13_brd-300x152.png" /></a>
<p>
<a href="https://ferdinandkeil.com/uploads/2012/05/Transistortester.zip"><i class="fa fa-floppy-o fa-2x" aria-hidden="true"></i> Transistortester.zip</a>
</p><p>
<a href="https://ferdinandkeil.com/uploads/2012/05/transistortester_source.zip"><i class="fa fa-floppy-o fa-2x" aria-hidden="true"></i> transistortester_source.zip</a>
</p>AVR-Transistortester2012-04-23T20:46:00+02:002012-04-23T20:46:00+02:00ferdinandtag:ferdinandkeil.com,2012-04-23:/avr-transistortester.html<p>Im Blog von <a class="reference external" href="http://dangerousprototypes.com/2011/12/13/avr-based-transitor-tester/">Dangerous
Prototypes</a>
bin ich über den <a class="reference external" href="http://www.mikrocontroller.net/articles/AVR-Transistortester">AVR-Transistortester von Markus
Frejek</a>
gestolpert. Das musste ich unbedingt haben. Was mir gar nicht gefiel
war die Spannungsversorgung mit einem 9V-Block und nachgeschaltetem
7805. Da musste eine bessere Lösung her, zumal ich kein Ladegerät für
9V-Block Akkus habe. Letztlich habe mich …</p><p>Im Blog von <a class="reference external" href="http://dangerousprototypes.com/2011/12/13/avr-based-transitor-tester/">Dangerous
Prototypes</a>
bin ich über den <a class="reference external" href="http://www.mikrocontroller.net/articles/AVR-Transistortester">AVR-Transistortester von Markus
Frejek</a>
gestolpert. Das musste ich unbedingt haben. Was mir gar nicht gefiel
war die Spannungsversorgung mit einem 9V-Block und nachgeschaltetem
7805. Da musste eine bessere Lösung her, zumal ich kein Ladegerät für
9V-Block Akkus habe. Letztlich habe mich dann für zwei in Reihe
geschaltete Mignon-Zellen entschieden. Die sind günstig, haben eine
recht hohe Energiedichte, sind leicht zu montieren (einen
entsprechenden Halter vorausgesetzt) und ich habe ein Ladegerät dafür.
Markus Schaltung verlangt allerdings nach 5V, die können meine zwei
Akkus natürlich nicht bieten. Ein Aufwärtswandler musste her. Nach
einigem Suchen bei <a class="reference external" href="http://de.farnell.com/">Farnell</a> und
<a class="reference external" href="http://www.digikey.com/">Digi-Key</a> fand ich den <a class="reference external" href="http://www.onsemi.com/PowerSolutions/product.do?id=NCP1402">OnSemi
NCP1402</a>.
Der IC ist in verschiedenen Versionen für Ausgangsspannungen von 1,9V
bis 5,0V verfügbar, integriert einen 200mA n-MOSFET und das alles in
einem SOT23-5 Gehäuse. Dank hoher Schaltfrequenz wird nur eine kleine
Induktivität benötigt. Perfekt für meine Zwecke.
Die automatische Abschaltung wollte ich beibehalten, allerdings in
einer Version mit einem p-MOSFET. Nach einigem hin und her hatte ich
einen Entwurf zusammen von dem ich <em>dachte</em>, dass er funktioniert. So
kann man sich irren! Unten abgebildet der erste Entwurf.</p>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2012/04/dcdc_auto_abschaltung.png"><img alt="" src="https://ferdinandkeil.com/uploads/2012/04/dcdc_auto_abschaltung-300x165.png" /></a>
<p>Es scheiterte letztlich an mehreren Fehlern. Zunächst hatte ich den
ADC des Mikrocontrollers direkt mit der Batterie verbunden um die
Spannung messen zu können. Das darf natürlich erst <em>nach</em> dem MOSFET
erfolgen, sonst fließt über diese Verbindung und die Schutzdioden des
Controllers permanent Strom. Da die Spannung i.d.R. zu gering ist für
den Betrieb des Controllers und des Displays passiert nicht viel, aber
die Energie ist verschwendet. Gleiches Ergebnis mit den Leitungen BTN
und PWR_ON. Außerdem konnte der Controller dank der Vorwärtsspannung
von D1 den Transistor Q1 bei niedriger Versorgungsspannung nicht
zuverlässig einschalten. Ok, zurück zum Zeichenbrett.
Nach einigem Probieren und diversen Flüchen bin ich dann bei folgender
Lösung gelandet.</p>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2012/04/dcdc_auto_abschaltung_2.png"><img alt="" src="https://ferdinandkeil.com/uploads/2012/04/dcdc_auto_abschaltung_2-300x154.png" /></a>
<p>Wenn zum Einschalten der Taster S1 gedrückt wird, lädt sich das Gate
von Q1 über die Diode D3. Sobald der Mikrocontroller mit Spannung
versorgt ist, zieht er PWR_ON auf high. Der n-MOSFET Q2 schaltet
durch, der Taster kann losgelassen werden. Die Schaltung läuft nun
weiter und kann vom Controller abgeschaltet werden (Leitung PWR_ON
auf low). Über den integrierten Pull-Up Widerstand ist BTN auf high
gezogen, wird der Taster im Betrieb erneut gedrückt liegt BTN über D1
auf GND und der Controller registriert die Eingabe. Für diese
Änderungen musste ich auf der Platine improvisieren. Unten Bilder vor
und nach den Änderungen.</p>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2012/04/IMG_0019-1600.jpg"><img alt="" src="https://ferdinandkeil.com/uploads/2012/04/IMG_0019-1600-300x225.jpg" /></a>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2012/04/IMG_0025-1600.jpg"><img alt="" src="https://ferdinandkeil.com/uploads/2012/04/IMG_0025-1600-300x225.jpg" /></a>
<p>Jetzt funktioniert die Schaltung einwandfrei. Nachdem die Fehler
behoben waren habe ich noch den Batteriehalter und das Display
montiert, fertig ist der Transistortester. In die Halterung passen wie
anfangs erwähnt zwei Mignon-Akkus, außerdem sind von unten ein Stecker
für Softwareupdates und das Poti für den Displaykontrast zugänglich.
Damit der Taster direkt neben den Batteriehalter passte musste ich
zwei schmale Schlitze in den Halter sägen. Jetzt passt es perfekt. Das
Display verfügt über eine hellgrüne Hintergrundbeleuchtung. Im Betrieb
braucht die Schaltung ca. 43mA bei 2,0V Batteriespannung (32mA bei
2,5V und ca. 25mA bei 3,0V), im ausgeschalteten Zustand ca. 300nA bei
2,0V. Damit sollten die Akkus (2000mAh) für etwa zwei Tage Betrieb und
mehrere Jahre Standby ausreichen.</p>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2012/04/IMG_0039-1600.jpg"><img alt="" src="https://ferdinandkeil.com/uploads/2012/04/IMG_0039-1600-300x225.jpg" /></a>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2012/04/IMG_0040-1600.jpg"><img alt="" src="https://ferdinandkeil.com/uploads/2012/04/IMG_0040-1600-300x225.jpg" /></a>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2012/04/IMG_0040-1600.jpg"><img alt="" src="https://ferdinandkeil.com/uploads/2012/04/IMG_0040-1600-300x225.jpg" /></a>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2012/04/IMG_0042-1600.jpg"><img alt="" src="https://ferdinandkeil.com/uploads/2012/04/IMG_0042-1600-300x225.jpg" /></a>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2012/04/IMG_0043-1600.jpg"><img alt="" src="https://ferdinandkeil.com/uploads/2012/04/IMG_0043-1600-300x225.jpg" /></a>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2012/04/IMG_0046-1600.jpg"><img alt="" src="https://ferdinandkeil.com/uploads/2012/04/IMG_0046-1600-300x225.jpg" /></a>
TPS61085 Evaluation Module2012-03-21T21:51:00+01:002012-03-21T21:51:00+01:00ferdinandtag:ferdinandkeil.com,2012-03-21:/tps61085-evaluation-module.html<p>Some time ago I ordered samples of TI's
<a class="reference external" href="http://focus.ti.com/docs/prod/folders/print/tps61085.html">TPS61085</a>
step-Up DC-DC converter. I have been looking for a DC-DC converter
capable of more than the usual 5-12 V output, and the TPS61085 looked
like a perfect match. This great little chip (MSOP and TSSOP packages)
can run off as few …</p><p>Some time ago I ordered samples of TI's
<a class="reference external" href="http://focus.ti.com/docs/prod/folders/print/tps61085.html">TPS61085</a>
step-Up DC-DC converter. I have been looking for a DC-DC converter
capable of more than the usual 5-12 V output, and the TPS61085 looked
like a perfect match. This great little chip (MSOP and TSSOP packages)
can run off as few as 2.3 V and output up to 18.5 V. It integrates an
2.0 A, 0.13 Ohm power switch and offers a selectable 650 kHz and 1.2 MHz
switching frequency. The high switching frequency makes it possible to
use very small inductors and capacitors, thus reducing the needed PCB
area.</p>
<p>After the parts had been lying around for some time I finally had the
time to layout a PCB to try them. The PCB layout is based on the layout
of the <a class="reference external" href="http://www.ti.com/lit/ug/slvu265a/slvu265a.pdf">TPS61085EVM</a>
evaluation module made by TI and the hints from the IC's datasheet. The
resulting PCB is just 29.21 x 25.40 mm in size, although it could still
be made smaller.</p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2011/10/tps61085_evaluation_v10.png"><img alt="image0" src="https://ferdinandkeil.com/uploads/2011/10/tps61085_evaluation_v10-300x262.png" /></a> <a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2011/10/tps61085_evaluation_v10_topbot.png"><img alt="image1" src="https://ferdinandkeil.com/uploads/2011/10/tps61085_evaluation_v10_topbot-300x142.png" /></a></p>
<p>I had two of these PCBs made and built one up for an output voltage of
15 V. As I didn't have the exact resistor values for the feedback
divider, the output voltage ended up to be 15.7 V instead of 15 V. I
then ran some tests.</p>
<div class="figure">
<img alt="" src="https://ferdinandkeil.com/uploads/2011/10/vripple_dcdc_1x_3.png" />
<p class="caption">Output ripple at low load current.</p>
</div>
<table border="1" class="docutils">
<colgroup>
<col width="69%" />
<col width="31%" />
</colgroup>
<tbody valign="top">
<tr><td>R<sub>load</sub></td>
<td>550 Ω</td>
</tr>
<tr><td>I<sub>load</sub></td>
<td>28.3 mA</td>
</tr>
<tr><td>V<sub>out</sub></td>
<td>15.88 V</td>
</tr>
<tr><td>V<sub>ripple,p-p</sub></td>
<td>17.2 mV</td>
</tr>
</tbody>
</table>
<div class="figure">
<img alt="" src="https://ferdinandkeil.com/uploads/2011/10/vripple_dcdc_1x_2.png" />
<p class="caption">Output ripple at high load current.</p>
</div>
<table border="1" class="docutils">
<colgroup>
<col width="65%" />
<col width="35%" />
</colgroup>
<tbody valign="top">
<tr><td>R<sub>load</sub></td>
<td>~ 156.7 Ω</td>
</tr>
<tr><td>I<sub>load</sub></td>
<td>101.6 mA</td>
</tr>
<tr><td>V<sub>out</sub></td>
<td>15.71 V</td>
</tr>
<tr><td>V<sub>ripple,p-p</sub></td>
<td>33.6 mV</td>
</tr>
</tbody>
</table>
<p>I originally planed to use this IC in a headphone amplifier, so I was
curious about the transient response of the circuit. I replicated the
measurement pictured in the datasheet to be able to compare the
results. Two paralleled resistors were connected as load, one of them
through a NPN transistor. A Teensy board was programmed to switch the
transistor at 1 kHz and 50 % duty-cycle. The results are shown below.</p>
<div class="figure">
<img alt="" src="https://ferdinandkeil.com/uploads/2012/02/transient_dcdc_x10.png" />
<p class="caption">Transient response.</p>
</div>
<table border="1" class="docutils">
<colgroup>
<col width="69%" />
<col width="31%" />
</colgroup>
<tbody valign="top">
<tr><td>R<sub>load</sub></td>
<td>360 Ω</td>
</tr>
<tr><td> </td>
<td>~ 78.3 Ω</td>
</tr>
<tr><td>I<sub>load</sub></td>
<td>44 mA</td>
</tr>
<tr><td> </td>
<td>~ 200 mA</td>
</tr>
<tr><td>V<sub>in</sub></td>
<td>4.99 V</td>
</tr>
<tr><td>V<sub>out</sub></td>
<td>15.94 V</td>
</tr>
<tr><td>V<sub>transient,p-p</sub></td>
<td>~ 200 mV</td>
</tr>
</tbody>
</table>
<p>Of course I also determined the efficiency of the circuit. At a load
current of 44 mA the efficiency turned out to be 82.75 %. Not too bad
for a first revision. The complete data is shown below.</p>
<table border="1" class="docutils">
<colgroup>
<col width="62%" />
<col width="38%" />
</colgroup>
<tbody valign="top">
<tr><td>R<sub>load</sub></td>
<td>360 Ω</td>
</tr>
<tr><td>I<sub>load</sub></td>
<td>44 mA</td>
</tr>
<tr><td>V<sub>in</sub></td>
<td>4.99 V</td>
</tr>
<tr><td>V<sub>out</sub></td>
<td>15.93 V</td>
</tr>
<tr><td>Efficiency</td>
<td>82.75 %</td>
</tr>
</tbody>
</table>
<p>The TPS61085 is a very capable little boost converter IC with many
possible applications. As I want to use it in an audio circuit, low
ripple at high frequencies is key. It also uses very little PCB area
and matching inductors are tiny and very cheap. From a 5 V USB power
supply this chip, together with an inverter can supply +/- 15 V for
precision OpAmps.
With an output ripple between 17 mV and 33 mV the circuit as is would
probably need additional regulation if used to power a tube or Class A
circuit. In this case the high ripple frequency is a problem, as most
common regulator ICs have pretty low attenuation at high frequencies.
A simple LC filter might suffice to attenuate the ripple, but I
haven't tested that yet.
As I want a power supply with a positive and negative rail, I am right
now looking at the <a class="reference external" href="http://www.ti.com/product/tps65130">TPS65130</a>,
which integrates two converters in one IC. Building an evaluation PCB
for this chip is next on the list.</p>
Repairing the Panasonic RF-B45 All Band Receiver2011-10-30T16:29:00+01:002011-10-30T16:29:00+01:00ferdinandtag:ferdinandkeil.com,2011-10-30:/repairing-the-panasonic-rf-b45-all-band-receiver.html<p>I just recently found a defect Panasonic RF-B45 All Band Receiver that
had been lying in a box waiting to be repaired. The Panasonic RF-B45
is a great little radio that can be run of 6V DC or 4 Alkaline
Batteries. It was actually still working, but could not be …</p><p>I just recently found a defect Panasonic RF-B45 All Band Receiver that
had been lying in a box waiting to be repaired. The Panasonic RF-B45
is a great little radio that can be run of 6V DC or 4 Alkaline
Batteries. It was actually still working, but could not be turned on
via the ON/OFF switch, as it was broken. I disassembled the device and
found that the keyboard uses cheap radial tactile switches that could
be easily replaced. I ordered 30 new "ALPS" switches from China,
reassembled the device and waited.
Finally the switches arrived and I could start replacing them. In the
following I will document the necessary steps.</p>
<p><strong>Step 1: Disassembling the receiver</strong></p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2011/10/IMG_0202-1600.jpg"><img alt="image0" src="https://ferdinandkeil.com/uploads/2011/10/IMG_0202-1600-300x199.jpg" style="width: 300px; height: 199px;" /></a> <a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2011/10/IMG_0220-1600_schrauben.jpg"><img alt="image1" src="https://ferdinandkeil.com/uploads/2011/10/IMG_0220-1600_schrauben-300x199.jpg" style="width: 300px; height: 199px;" /></a></p>
<p>The Panasonic RF-B45 is easily cracked open. Just remove the antenna and
then six screws. In the above image I have marked the position of all
screws. After the back is taken off the mainboard can be removed.</p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2011/10/IMG_0226-1600.jpg"><img alt="image2" src="https://ferdinandkeil.com/uploads/2011/10/IMG_0226-1600-300x199.jpg" style="width: 300px; height: 199px;" /></a> <a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2011/10/IMG_0227-1600_schrauben.jpg"><img alt="image3" src="https://ferdinandkeil.com/uploads/2011/10/IMG_0227-1600_schrauben-199x300.jpg" style="width: 199px; height: 300px;" /></a></p>
<p>The switches are on an extra PCB that is connected via a ribbon cable.
Remove the connector carefully and then the two screws holding back the
PCB. Again, the screws and the connector are marked in the image.</p>
<p><strong>Step 2: Unsoldering the switches</strong></p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2011/10/IMG_0230-1600.jpg"><img alt="image4" src="https://ferdinandkeil.com/uploads/2011/10/IMG_0230-1600-300x199.jpg" style="width: 300px; height: 199px;" /></a> <a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2011/10/IMG_0232-1600.jpg"><img alt="image5" src="https://ferdinandkeil.com/uploads/2011/10/IMG_0232-1600-300x199.jpg" style="width: 300px; height: 199px;" /></a></p>
<p>Having the PCB removed one can start the tedious task of unsoldering all
switches. You can of course just replace the broken switches, but to be
on the safe side I just replaced all of them. One pad lifted from the
PCB while I unsoldered the switches, but all in all the PCB endured this
procedure quite well. As it is neither plated through nor of FR4
material you have to be careful not to destroy the delicate pads and
traces. The metal shield on the back of the LC display covers three
switches and therefore has to be removed, too. This is time consuming
work but not difficult at all.</p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2011/10/IMG_0236-1600.jpg"><img alt="image6" src="https://ferdinandkeil.com/uploads/2011/10/IMG_0236-1600-300x199.jpg" style="width: 300px; height: 199px;" /></a></p>
<p><strong>Step 3: Soldering the new switches</strong></p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2011/10/IMG_0240-1600.jpg"><img alt="image7" src="https://ferdinandkeil.com/uploads/2011/10/IMG_0240-1600-300x199.jpg" style="width: 300px; height: 199px;" /></a> <a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2011/10/IMG_0241-1600.jpg"><img alt="image8" src="https://ferdinandkeil.com/uploads/2011/10/IMG_0241-1600-300x199.jpg" style="width: 300px; height: 199px;" /></a></p>
<p>After all switches are gone clean the PCB. Then start soldering the new
switches. This again takes some time. I soldered one leg at first, then
reflowing the joint and pressing the switch flush to the PCB. I then
soldered the second leg. After finishing all joints cut the legs, drown
them in flux and reflow them again. Do a short inspection under
magnification and make sure that all joints are nice and shiny. Then
clean the PCB again.</p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2011/10/IMG_0244-1600.jpg"><img alt="image9" src="https://ferdinandkeil.com/uploads/2011/10/IMG_0244-1600-300x199.jpg" style="width: 300px; height: 199px;" /></a></p>
<p><strong>Step 4: Assembling the device and testing</strong></p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2011/10/IMG_0252-1600.jpg"><img alt="image10" src="https://ferdinandkeil.com/uploads/2011/10/IMG_0252-1600-300x199.jpg" style="width: 300px; height: 199px;" /></a></p>
<p>Now you can put the receiver back together again. Fasten the two
screws fixing the PCB and then carefully connect the ribbon cable
connector. Put the mainboard back in the front part of the case and
put the back on. After all screws are fastened and the antenna is
mounted the receiver should be working as normal.
Congratulations, you have rescued one more device from going to the
landfill.</p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2011/10/IMG_0255-1600.jpg"><img alt="image11" src="https://ferdinandkeil.com/uploads/2011/10/IMG_0255-1600-300x199.jpg" style="width: 300px; height: 199px;" /></a></p>
Shuttle FS51 v2.0 (SS51G) LAN problem2011-07-11T11:57:00+02:002011-07-11T11:57:00+02:00ferdinandtag:ferdinandkeil.com,2011-07-11:/shuttle-fs51-v2-0-ss51g-lan-problem.html<p>These days I swiped the Windows installation from a Shuttle XPC system
and set it up with a clean install as I plan to give it away. While I
was cleaning the mainboard from dust, I found the single SRAM module
to be sitting in the slot DIMM1. On most …</p><p>These days I swiped the Windows installation from a Shuttle XPC system
and set it up with a clean install as I plan to give it away. While I
was cleaning the mainboard from dust, I found the single SRAM module
to be sitting in the slot DIMM1. On most boards a single stick of RAM
is expected to be put in slot #0, so I swapped the module over to the
first connector. I then updated the BIOS and installed Windows XP SP2,
but not without difficulties. The installation would not finish with
an AGP graphics card connected, and even after I removed it the
network adapter was neither recognized by Windows nor a Linux system.
Downgrading the BIOS and clearing the EEPROM did not help, so in an
desperate attempt to restore the LAN adapter I plugged the RAM module
once again in slot #1. And you know what, Windows boots up and
recognizes the adapter just fine. This is not mentioned in the
mainboard manual and installation guide so I had to find out the hard
way.
So if your Shuttle FS51 v2.0 (aka SS51G) acts weird try to change the
RAM slots.</p>
<hr class="docutils" />
<p><strong>Update 25.08.2011</strong>
Well, as it turned out the RAM wasn't the problem. After I reinstalled
Windows XP on the machine the network card did not show up in the
device manager. In a desperate attempt to restore the network
connection I measured the BIOS backup battery and voilà, it was empty
(down to 1.5V). I replaced it with a fresh one and the network card
magically appeared in the device manager. Everything seems to be back
to normal now so I can finally finish the installation process.</p>
<hr class="docutils" />
<p><strong>Update 27.08.2011</strong>
The network adapter disappeared again! A CMOS clear brought it back
for some time, but then it disappeared again. The CMOS clear should be
done after every BIOS update by moving the on-board jumper to its
second position and back after several seconds - lesson learned. After
checking the power supply (all good), the caps on the mainboard (also
good) and a lot of hair tearing I finally came back to the BIOS
settings. I hadn't changed the "Reset Configuration Data" switch
before so I gave it a try. And the network adapter finally came back.
It even stayed after I changed back the switch to Disabled. I don't
now how long it will take until my RTL8139 goes back to its happy
place but for now I'm confident that I solved the problem.
I read about the meaning of this BIOS setting and what the <a class="reference external" href="http://www.dewassoc.com/support/bios/escd.htm">Extended
System Configuration Data
(ESCD)</a> is, and it
seems plausible that this was the problem. Time will tell...</p>
<hr class="docutils" />
<p><strong>Update 28.08.2011</strong>
I give up. The network card has been and gone. Under the screen of
night it left and I have been unable to bring it back. From the looks
of it something is seriously messed up with this PC, but I won't
bother even further.</p>
<p>
<center><p><strong>R.I.P. RTL8139</strong>
2003 - 2011</p>
</center>
</p>How to Restore a locked up Seagate Dockstar2011-06-30T16:27:00+02:002011-06-30T16:27:00+02:00ferdinandtag:ferdinandkeil.com,2011-06-30:/how-to-restore-a-locked-up-seagate-dockstar.html<p>Recently I wanted to try my LCD extension for the Seagate Dockstar with
the actual hardware, but had to realize that my unit was broken. A quick
test with a serial cable revealed that the bootloader was not starting.
For embedded systems that's usually the worst case scenario. The only …</p><p>Recently I wanted to try my LCD extension for the Seagate Dockstar with
the actual hardware, but had to realize that my unit was broken. A quick
test with a serial cable revealed that the bootloader was not starting.
For embedded systems that's usually the worst case scenario. The only
chance left to restore the device is to reprogram the internal flash
memory using a JTAG debug connection. Luckily Seagate went so far to
include a 2mm-pitch male connector on the mainboard with all JTAG pins
brought out. I still had an adapter cable for the 2mm pitch connector
lying around from the last Dockstar rescue, so I could easily connect to
the system. Bus Pirate to the rescue!</p>
<p>As I started with a vanilla Ubuntu 9.04 Karmic Koala system in respect
to JTAG tools, I will describe all steps necessary from the first
download to the working system.</p>
<p>The necessary tools for the process can be bought from Seeedstudio. I
used the Bus Pirate (v2go) and a Seeeduino (v1.1). Newer models should
work as well.
<strong>DO NOT USE A REGULAR ARDUINO FOR THIS PROCEDURE, AS IT WILL KILL
YOUR DOCKSTAR! THE SUPPLY VOLTAGE OF THE SEEEDUINO CAN BE SELECTED AND
HAS TO BE SET TO 3,3V!</strong></p>
<p><strong>DISCLAIMER:</strong> I can not be hold liable for any damages, data loss or
other problems being caused by the steps outlined in the following
document. I do not guarantee for the correctness of the offered
description - so you have to think for yourself and check everything
twice. If you're at the point where you need to reflash your device
you already have come to terms with it being broken. The following
steps might work for you or leave you with a nice paper weight.
This tutorial is for the experienced user only. Don't proceed if
you're not absolutely sure what you're doing!</p>
<div class="section" id="step-1-checkout-and-compile-openocd">
<h2>Step 1: Checkout and compile OpenOCD</h2>
<p>To actually talk the processor via JTAG one needs a special software.
The open-source offering for this cause is
<a class="reference external" href="http://openocd.berlios.de/web/">OpenOCD</a>. My Ubuntu system is pretty
old, so the a OpenOCD version including Bus Pirate support was not in
the repository. To compile OpenOCD we first need to install some
necessary tools. In a terminal type</p>
<div class="highlight"><pre><span></span>sudo apt-get install git-core libtool texinfo automake checkinstall
</pre></div>
<p>GIT is needed to checkout the latest version of OpenOCD; libtool,
texinfo and automake are necessary for OpenOCD to compile; checkinstall
creates a package after a successful make, which makes it easier to
remove the program afterwards.</p>
<p>First of, cd to a directory of your choice and type</p>
<div class="highlight"><pre><span></span>git clone git://openocd.git.sourceforge.net/gitroot/openocd/openocd
</pre></div>
<p>Now you have a local copy of the latest OpenOCD sources. To compile and
install OpenOCD type</p>
<div class="highlight"><pre><span></span><span class="nb">cd</span> openocd
./bootstrap
./configure --enable-buspirate --enable-maintainer-mode
make
sudo checkinstall
</pre></div>
<p>After a successful checkinstall the command openocd should be available.</p>
</div>
<div class="section" id="step-2-download-required-files">
<h2>Step 2: Download required files</h2>
<p>You will need four files to bring your Dockstar back to life:</p>
<ul class="simple">
<li>a config file for OpenOCD</li>
<li>an image of the uboot bootloader</li>
<li>an image of the Linux kernel and a matching ram-disk</li>
<li>a firmware for the BusPirate supporting OpenOCD.</li>
</ul>
<p>As I couldn't find the original image files for the Dockstar, I used the
modified uboot bootloader and rescue system image compiled by Jeff
Doozan. To ease the installation I packed all necessary files in an
archive that can be downloaded <a class="reference external" href="https://ferdinandkeil.com/uploads/2011/06/dockstar.zip">here</a>.
You can always download those files yourself:</p>
<div class="highlight"><pre><span></span>mkdir dockstar
<span class="nb">cd</span> dockstar
wget http://plume.redox.ws/data/documents/dockstar.cfg
wget http://jeff.doozan.com/debian/uboot/files/uboot/uboot.mtd0.dockstar.jeff-2010-10-23.kwb
wget http://jeff.doozan.com/debian/rescue/uImage-mtd1.img
wget http://jeff.doozan.com/debian/rescue/rootfs-mtd2.img
wget http://dangerousprototypes.com/forum/download/file.php?id<span class="o">=</span><span class="m">3493</span>
</pre></div>
</div>
<div class="section" id="step-3-set-up-your-tftp-server">
<h2>Step 3: Set-up your TFTP server</h2>
<p>To complete the restoration process you need a TFTP server in your
network. You can find several tutorials for Ubuntu on the net (e.g.
<a class="reference external" href="http://blog.tuxcoder.com/2008/06/configure-tftp-server-in-ubuntu.html">http://blog.tuxcoder.com/2008/06/configure-tftp-server-in-ubuntu.html</a>).
The server has to be able to find the following files:</p>
<ul class="simple">
<li>uImage-mtd1.img</li>
<li>rootfs-mtd2.img</li>
</ul>
<p>Of course the server has to be in the same network as the Dockstar.</p>
</div>
<div class="section" id="step-4-update-and-configure-the-buspirate">
<h2>Step 4: Update and configure the BusPirate</h2>
<p>Unfortunately the BusPirate firmware capable of talking to OpenOCD
can't be flashed using a Linux system (as far as I know). I tried it
but it did not work with the supplied update tool. The <a class="reference external" href="http://dangerousprototypes.com/docs/Ds30_Loader_GUI">ds30 Loader
GUI for
Windows</a> works
fine. You can find more on the BusPirate update procedure in the
<a class="reference external" href="http://dangerousprototypes.com/docs/Bus_Pirate">Dangerous Prototypes
Wiki</a>.
After you updated the BusPirate try to connect to it via OpenOCD.
First you have to alter the config file to use the BusPirate as
interface:</p>
<p>Replace</p>
<div class="highlight"><pre><span></span># I'm using a wiggler compatible cable
source [find interface/buspirate.cfg]
source [find target/feroceon.cfg]
jtag_khz 500
jtag_nsrst_delay 500
</pre></div>
<p>With</p>
<div class="highlight"><pre><span></span>interface buspirate
buspirate_port /dev/ttyUSB0
buspirate_speed fast
buspirate_vreg 0
buspirate_pullup 0
</pre></div>
<p>This configuration worked for me. Now try:</p>
<div class="highlight"><pre><span></span>openocd -f ./dockstar.cfg
</pre></div>
<p>If OpenOCD sucessfully talks to the BusPirate this step is completed.</p>
</div>
<div class="section" id="step-5-connect-the-bus-pirate-and-seeeduino">
<h2>Step 5: Connect the Bus Pirate and Seeeduino</h2>
<p>Before the Seeeduino gets connected to anything you have to make sure
the on-board microcontroller does not interfere with the communication
between the Dockstar and your PC. The easiest way to achieve this, is a
simple program that configures the serial ports on the controller as
inputs. Inputs operate in an high-impedance state and do not affect the
serial connection. The listed program will do the job:</p>
<div class="highlight"><pre><span></span><span class="kr">void</span><span class="w"> </span><span class="nb">setup</span><span class="p">()</span><span class="w"></span>
<span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nf">pinMode</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="kr">INPUT</span><span class="p">);</span><span class="w"></span>
<span class="w"> </span><span class="nf">pinMode</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="kr">INPUT</span><span class="p">);</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
<span class="kr">void</span><span class="w"> </span><span class="nb">loop</span><span class="p">()</span><span class="w"></span>
<span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="nf">delay</span><span class="p">(</span><span class="mi">1000</span><span class="p">);</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</pre></div>
<p>So connect the Seeeduino to the PC and upload the program. Disconnect it
again and you are ready to go on.</p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2011/06/debug_header.png"><img alt="Dockstar Debug Header" class="alignnone size-medium wp-image-536" src="https://ferdinandkeil.com/uploads/2011/06/debug_header-300x155.png" style="width: 300px; height: 155px;" /></a></p>
<div class="line-block">
<div class="line"><br /></div>
</div>
<table border="1" class="docutils">
<colgroup>
<col width="30%" />
<col width="36%" />
<col width="33%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Dockstar</th>
<th class="head">Bus Pirate</th>
<th class="head">Seeeduino</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>1 Vcc</td>
<td>--</td>
<td>--</td>
</tr>
<tr><td>2 GND</td>
<td>GND</td>
<td>GND</td>
</tr>
<tr><td>3 n_TRST</td>
<td>AUX</td>
<td>--</td>
</tr>
<tr><td>4 TxD</td>
<td>--</td>
<td>TX</td>
</tr>
<tr><td>5 TDI</td>
<td>MOSI</td>
<td>--</td>
</tr>
<tr><td>6 RxD</td>
<td>--</td>
<td>RX</td>
</tr>
<tr><td>7 TMS</td>
<td>CS</td>
<td>--</td>
</tr>
<tr><td>8 ???</td>
<td>--</td>
<td>--</td>
</tr>
<tr><td>9 TCK</td>
<td>CLK</td>
<td>--</td>
</tr>
<tr><td>10 TDO</td>
<td>MISO</td>
<td>--</td>
</tr>
</tbody>
</table>
<div class="line-block">
<div class="line"><br /></div>
</div>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2011/06/IMG_1306-1440.jpg"><img alt="Flashing setup" class="alignnone size-medium wp-image-538" src="https://ferdinandkeil.com/uploads/2011/06/IMG_1306-1440-300x141.jpg" style="width: 300px; height: 141px;" /></a></p>
<p>You will need some kind of adapter for the 2mm-pitch male connector on
the Dockstar board. I made one myself using a female connector and some
cable. Follow the connection table thoroughly, it might save your device
later on. However, while connecting the three devices do not connect any
of them to a PC or power.</p>
<p>Now, first of all, power up the Dockstar. As its supposedly broken not
much will happen now. When the Dockstar is running you can connect the
Bus Pirate and Seeeduino to your PC. Execute lsusb in a terminal to
check if both devices have successfully been connected. To talk to the
Dockstar via the Seeeduino you will have to open a terminal program. I
used screen:</p>
<div class="highlight"><pre><span></span>screen /dev/ttyUSB1 <span class="m">115200</span>
</pre></div>
<p>The actual device file created for the Seeeduino depends on your
configuration and order of connection. To make sure you opened the right
device connect the leads for RX and TX together and check for an echo in
the terminal.</p>
</div>
<div class="section" id="step-6-flash-the-bootloader">
<h2>Step 6: Flash the bootloader</h2>
<p>Now you're ready to restore the Dockstar. Open three terminals. In the
first one start OpenOCD with the command given under step 4, in the
second open a serial connection to the Seeeduino (see step 5) and in the
third type:</p>
<div class="highlight"><pre><span></span>telnet localhost <span class="m">4444</span>
</pre></div>
<p>Now you're connected to the OpenOCD console. The following commands let
the CPU on the Dockstar enter the debug mode and flash the bootloader:</p>
<div class="highlight"><pre><span></span>init
<span class="c1"># first type in the "halt" command WITHOUT pressing ENTER</span>
halt
<span class="c1"># now press the reset key on the Dockstar, hold it and press ENTER the same moment you release it</span>
<span class="c1"># you should now read something like "target state: halted"</span>
dockstar_init
load_image uboot.mtd0.dockstar.jeff-2010-10-23.kwb 0x800000
<span class="c1"># of course you can rename the image to a shorter filename</span>
<span class="c1"># when the image has been loaded successfully continue</span>
resume <span class="m">0</span>×800200
</pre></div>
<p>Now should switch to the serial connection IMMEDIATELY. You should see
the bootprompt output of uBoot. Disrupt the boot process by pressing a
key. DO NOT press reset as of now, as the bootloader is executed from
RAM and will be lost after a reset.
In the uBoot prompt type:</p>
<div class="highlight"><pre><span></span>nand erase
nand write.e <span class="m">0</span>×800000 <span class="m">0</span>×0 <span class="m">0</span>×80000
</pre></div>
<p>Now you're half way through. If everything worked out well you can
disconnect the BusPirate and press reset. You should again see the boot
prompt on the serial connection. The bootloader does not find a kernel
image therefore will be stuck in a loop. Jeff Doozan's modified
bootloader is capable of booting of an USB stick. If you happen to have
one, try it.</p>
</div>
<div class="section" id="step-7-flash-the-rescue-system">
<h2>Step 7: Flash the rescue system</h2>
<p>This step is not really necessary but I found it extremly helpful.
Disrupt the boot sequence at startup and enter the following commands:</p>
<div class="highlight"><pre><span></span>setenv ipaddr xxx.xxx.xxx.xxx
<span class="c1"># has to be in your network and unused</span>
setenv serverip xxx.xxx.xxx.xxx
<span class="c1"># ip address of your TFTP server</span>
setenv ethaddr xx:xx:xx:xx:xx:xx
<span class="c1"># MAC address, written on the bottom of the case</span>
saveenv
ping <span class="k">$(</span>serverip<span class="k">)</span>
<span class="c1"># checks the connection to the server</span>
</pre></div>
<p>Now we will flash Jeff Doozan's great rescue Linux to the device. With
it the Dockstar can be booted without an USB stick. Enter the following
commands:</p>
<div class="highlight"><pre><span></span>nand erase 0x100000 0x400000
tftp 0x800000 uImage-mtd1.img
nand write.e 0x800000 0x100000 0x380000
tftp 0x1000000 rootfs-mtd2.img
</pre></div>
<p>The images are now flashed, but uBoot will ignore them if we don't
change its configuration:</p>
<div class="highlight"><pre><span></span>setenv rescue_set_bootargs <span class="s1">'setenv bootargs console=$console ubi.mtd=2 root=ubi0:rootfs ro rootfstype=ubifs $mtdparts $rescue_custom_params'</span>
setenv rescue_bootcmd <span class="s1">'if test $rescue_installed -eq 1; then run rescue_set_bootargs; nand read.e 0x800000 0x100000 0x400000; bootm 0x800000; else run pogo_bootcmd; fi'</span>
setenv bootcmd <span class="s1">'run bootcmd_usb; usb stop; run rescue_bootcmd; reset'</span>
saveenv
run rescue_bootcmd
</pre></div>
<p>The Dockstar should now be booting the rescue system.
When no USB stick with a working Linux system is connected to the
Dockstar it will now try to boot the rescue system. So whatever
happens, you will still have a working system on your device.</p>
<p><strong>NOTICE:</strong> somehow the Linux kernel would not start as long as the Bus
Pirate was still connected to the device.</p>
<p><em>Sources</em></p>
<ul class="simple">
<li><a class="reference external" href="http://www.yourwarrantyisvoid.com/2010/09/08/dead-dockstar-resurrected-with-jtag/">http://www.yourwarrantyisvoid.com/2010/09/08/dead-dockstar-resurrected-with-jtag/</a></li>
<li><a class="reference external" href="http://jeff.doozan.com/debian/">http://jeff.doozan.com/debian/</a></li>
<li><a class="reference external" href="http://forum.doozan.com/read.php?3,3826,3826#msg-3826">http://forum.doozan.com/read.php?3,3826,3826#msg-3826</a></li>
<li><a class="reference external" href="http://wiki.ubuntuusers.de/PXE-Installation">http://wiki.ubuntuusers.de/PXE-Installation</a></li>
<li><a class="reference external" href="http://plume.redox.ws/article13/dockstar-debricking-jtag-with-buspirate">http://plume.redox.ws/article13/dockstar-debricking-jtag-with-buspirate</a></li>
<li><a class="reference external" href="http://blog.hodgepig.org/2010/04/13/545/">http://blog.hodgepig.org/2010/04/13/545/</a></li>
<li><a class="reference external" href="http://forum.doozan.com/read.php?2,1169,1361#msg-1361">http://forum.doozan.com/read.php?2,1169,1361#msg-1361</a></li>
</ul>
</div>
Firefox mit NoScript und jDownloader click and load2011-06-27T00:04:00+02:002011-06-27T00:04:00+02:00ferdinandtag:ferdinandkeil.com,2011-06-27:/firefox-mit-noscript-und-jdownloader-click-and-load.html<p>Seit ich Firefox mit der <a class="reference external" href="https://addons.mozilla.org/de/firefox/addon/noscript/">Erweiterung
NoScript</a>
einsetze funktioniert die sehr praktische <a class="reference external" href="http://jdownloader.org/knowledge/wiki/glossary/cnl2">click and load
Funktion</a> des
<a class="reference external" href="http://jdownloader.org/">jDownloader</a> nicht mehr. Kein Wunder, setzt
diese Funktion doch auf wenig schönes <a class="reference external" href="http://de.wikipedia.org/wiki/Cross-Site_Scripting">Cross Site Scripting
(XSS)</a>. Allerdings
kann man in der Konfiguration des NoScript Addons die Einstellungen so
anpassen, dass click and load …</p><p>Seit ich Firefox mit der <a class="reference external" href="https://addons.mozilla.org/de/firefox/addon/noscript/">Erweiterung
NoScript</a>
einsetze funktioniert die sehr praktische <a class="reference external" href="http://jdownloader.org/knowledge/wiki/glossary/cnl2">click and load
Funktion</a> des
<a class="reference external" href="http://jdownloader.org/">jDownloader</a> nicht mehr. Kein Wunder, setzt
diese Funktion doch auf wenig schönes <a class="reference external" href="http://de.wikipedia.org/wiki/Cross-Site_Scripting">Cross Site Scripting
(XSS)</a>. Allerdings
kann man in der Konfiguration des NoScript Addons die Einstellungen so
anpassen, dass click and load trotzdem funktioniert. Allerdings muss
dies für jede Seite die die Funktion einsetzt neu geschehen.</p>
<p>Folgende Konfiguration ist vorzunehmen:
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2011/06/noscript_settings_xss.png"><img alt="NoScript Einstellungen XSS" src="https://ferdinandkeil.com/uploads/2011/06/noscript_settings_xss-300x207.png" style="width: 300px; height: 207px;" /></a>
Unter <strong>Einstellungen > Erweitert > Cross-Site Scripting (XSS)</strong>
eintragen:</p>
<div class="highlight"><pre><span></span>^http://127.0.0.1:9666/flash/addcrypted2$
</pre></div>
<p>Diese Regel ist nur einmal nötig.</p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2011/06/noscript_settings_abe.png"><img alt="NoScript Einstellungen ABE" src="https://ferdinandkeil.com/uploads/2011/06/noscript_settings_abe-300x207.png" style="width: 300px; height: 207px;" /></a>
Unter <strong>Einstellungen > Erweitert > ABE > Regelsätze > SYSTEM</strong>
eintragen:</p>
<div class="highlight"><pre><span></span>Site http://localhost:9666 Accept from http://*.domain.net Deny
</pre></div>
<p>Diese Regel muss für jede Domain angepasst werden.</p>
<p><img alt="jDownloader click and load" src="https://ferdinandkeil.com/uploads/2011/06/jdownloader_cnl.png" style="width: 198px; height: 68px;" />
Nun sollte click and load wieder funktionieren.</p>
FLAC und MKV im Windows Media Player 122011-06-25T12:56:00+02:002011-06-25T12:56:00+02:00ferdinandtag:ferdinandkeil.com,2011-06-25:/flac-und-mkv-im-windows-media-player-12.html<p>Da der Windows Media Player (WMP) in Version 12 eine akzeptable
Medien-Bibliothek mitbringt kam ich am Laptop bisher ohne Winamp aus.
Als ich dann jedoch ein Album im
<a class="reference external" href="http://de.wikipedia.org/wiki/Free_Lossless_Audio_Codec">FLAC</a> Format
abspielen wollte, musste ich feststellen, dass dies nicht ohne weiteres
funktioniert. Nachdem ich mich durch einen Wust an Forumbeiträgen
gelesen …</p><p>Da der Windows Media Player (WMP) in Version 12 eine akzeptable
Medien-Bibliothek mitbringt kam ich am Laptop bisher ohne Winamp aus.
Als ich dann jedoch ein Album im
<a class="reference external" href="http://de.wikipedia.org/wiki/Free_Lossless_Audio_Codec">FLAC</a> Format
abspielen wollte, musste ich feststellen, dass dies nicht ohne weiteres
funktioniert. Nachdem ich mich durch einen Wust an Forumbeiträgen
gelesen hatte fand ich die Lösung auf der Seite des <a class="reference external" href="http://bmproductions.fixnum.org/index.htm?http://bmproductions.fixnum.org/wmptagplus/">WMP Tag Plus
Plugins</a>.
Zusammen mit den <a class="reference external" href="http://www.xiph.org/dshow/">Open Codecs von
Xiph.Org</a> lassen sich so die FLAC Dateien
nicht nur abspielen, sondern erscheinen auch korrekt getaggt in der
Bibliothek. Für das eigentlich abspielen sind nur die Codecs nötig,
allerdings erkennt der WMP dann den Interpreten etc. nicht.</p>
<p>Ein Test mit einer MKV Datei in 1080p Auflösung und mit DTS Ton zeigte:
auch dieses Format verträgt der WMP nicht. Also mussten auch hier Codecs
her. Folgendes wird benötigt:</p>
<ul class="simple">
<li>der <a class="reference external" href="http://haali.su/mkv/">Haali Media Splitter</a> für den Matroska
Container,</li>
<li>die Codecs aus dem <a class="reference external" href="http://sourceforge.net/projects/ffdshow-tryout/">ffdshow tryout
Paket</a> und</li>
<li>den <a class="reference external" href="http://ac3filter.net/wiki/Download_AC3Filter">AC3 Filter</a>.</li>
</ul>
<p>Ob das ffdshow Paket wirklich nötig ist um
<a class="reference external" href="http://de.wikipedia.org/wiki/H264">h264</a> abzuspielen ist mir noch
nicht ganz klar. Nach der Deinstallation von ffdshow funktionierte es
weiterhin. Mit der oben angegeben Kombination aus Splittern und Codecs
funktioniert es jedoch hundertprozentig.</p>
<p>Die <strong>einfachste Lösung</strong> für derartige Probleme ist jedoch gleich den
<a class="reference external" href="http://www.videolan.org/">VLC Media Player</a> zur verwenden. Für MKV
Dateien hat das noch den Vorteil, dass die Tonspuren und Untertitel
direkt im Player umgeschaltet werden können. Daher werde ich für Videos
auch beim VLC Player bleiben, aber für Musik ist der Windows Media
Player dank Bibliothek einfach besser geeignet.</p>
csv2latex2011-02-28T21:20:00+01:002011-02-28T21:20:00+01:00ferdinandtag:ferdinandkeil.com,2011-02-28:/csv2latex.html<p>Da ich zur Zeit an meiner Bachelor-Arbeit schreibe muss ich mich
wieder intensiver mit LaTex auseinander setzen. Manche Arbeiten nimmt
LaTex einem beim Satz eines Dokuments ab, manche macht es schwerer als
nötig. Meiner Meinung gehört das Erstellen von Tabellen zur zweiten
Kategorie. Daher erstelle ich sie vorher in OpenOffice …</p><p>Da ich zur Zeit an meiner Bachelor-Arbeit schreibe muss ich mich
wieder intensiver mit LaTex auseinander setzen. Manche Arbeiten nimmt
LaTex einem beim Satz eines Dokuments ab, manche macht es schwerer als
nötig. Meiner Meinung gehört das Erstellen von Tabellen zur zweiten
Kategorie. Daher erstelle ich sie vorher in OpenOffice Calc und
überführe sie anschließend in LaTex Markup. Bei kleinen Tabellen ist
das kein Problem, was aber tun wenn man es mit einer umfangreicheren
Tabelle mit Messwerten zu tun hat. Es musste eine automatische Lösung
her.</p>
<p>Es gibt zwar auch Wege direkt aus Calc LaTex zu exportieren, aber
damit wollte ich mich nicht befassen. CSV habe ich schon bei anderen
Gelegenheiten als Austauschformat verwendet, da viele Anwendungen
damit umgehen können und es trotzdem lesbar ist. Ein Konverter CSV
nach LaTex musste her. Da bietet sich das wunderbare Tool
<a class="reference external" href="https://launchpad.net/csv2latex">csv2latex</a> von Benoît Rouits an.
Die letzte und aktuelle Version stammt zwar aus 2009, aber das
Programm ist ausgereift und bietet reichlich Optionen um mit jedem CSV
Format klarzukommen.</p>
<p>Ich habe es mit gcc unter Windows XP ohne Probleme kompilieren können.
Es funktioniert soweit ich es getestet habe ohne Probleme. Die .exe
und der Quelltext habe ich angehängt:</p>
<div class="line-block">
<div class="line"><br /></div>
</div>
<a href="https://ferdinandkeil.com/uploads/2011/02/csv2latex-0.14.zip"><i class="fa fa-floppy-o fa-2x" aria-hidden="true"></i> csv2latex-0.14</a>ECC82 / IRF510 Kopfhörerverstärker2011-01-15T13:10:00+01:002011-01-15T13:10:00+01:00ferdinandtag:ferdinandkeil.com,2011-01-15:/ecc82-irf510-kopfhorerverstarker.html<p>Ein Projekt mit Röhren umzusetzen hat mich schon seit langer Zeit
gereizt. Als ich auf <a class="reference external" href="http://diyaudioprojects.com/">DIY Audio
Projects</a> Rogers Gomez Entwurf für
einen <a class="reference external" href="http://diyaudioprojects.com/Solid/12AU7-IRF510-LM317-Headamp/">ECC82 / IRF510 basierten
Hybridverstärker</a>
gesehen habe wusste ich, der muss es sein. Die Vorteile der Schaltung
ist die sehr gute Klangqualität, die einfache Konstruktion und die
niedrige …</p><p>Ein Projekt mit Röhren umzusetzen hat mich schon seit langer Zeit
gereizt. Als ich auf <a class="reference external" href="http://diyaudioprojects.com/">DIY Audio
Projects</a> Rogers Gomez Entwurf für
einen <a class="reference external" href="http://diyaudioprojects.com/Solid/12AU7-IRF510-LM317-Headamp/">ECC82 / IRF510 basierten
Hybridverstärker</a>
gesehen habe wusste ich, der muss es sein. Die Vorteile der Schaltung
ist die sehr gute Klangqualität, die einfache Konstruktion und die
niedrige notwendige Versorgungsspannung von etwa 12 V. Da die 12 V
auch ohne Probleme von einem Akku zur Verfügung gestellt werden können
kann Rauschen durch die Spannungsversorgung nahezu komplett eliminiert
werden.</p>
<p>Den Schaltplan habe ich im Großen und Ganzen übernommen. Vor den
Kopfhörerausgang habe ich eine Anschaltverzögerung basierend auf der
Schaltung des <a class="reference external" href="http://diyforums.org/MAX/MAXe12.php">Millet Hybrid MAX e12
Delay</a> gesetzt. Die
Verzögerung beträgt in etwa 30 Sekunden, bis dahin ist die Röhre warm
und die Kapazitäten am Ausgang aufgeladen. Vom Aufbau der Schaltung
habe ich leider keine Bilder. Es gab dabei ein Problem: die Bohrungen
für den Röhrensockel waren zu klein, ich musste sie aufbohren und habe
die Pads anschließend mit Silberdraht verstärkt.</p>
<p>Der Verstärker klingt ausgezeichnet und ist sehr kompakt (Grundfläche
85 x 56 mm). Für ausgiebige Tests
(<a class="reference external" href="http://audio.rightmark.org/index_new.shtml">RMAA</a>) hatte ich
leider noch keine Zeit, auch ein passendes rauscharmes Netzteil fehlt
mir noch. Bisher habe ich einen 12 V Bleigel-Akku als Quelle
verwendet, das Netzteil ist in Planung.</p>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2011/01/IMG_0936-1600.jpg"><img alt="" class="img-gallery" src="https://ferdinandkeil.com/uploads/2011/01/IMG_0936-1600-150x150.jpg" /></a>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2011/01/IMG_0928-1600.jpg"><img alt="" class="img-gallery" src="https://ferdinandkeil.com/uploads/2011/01/IMG_0928-1600-150x150.jpg" /></a>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2011/01/IMG_0931-1600.jpg"><img alt="" class="img-gallery" src="https://ferdinandkeil.com/uploads/2011/01/IMG_0931-1600-150x150.jpg" /></a>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2011/01/IMG_0933-1600.jpg"><img alt="" class="img-gallery" src="https://ferdinandkeil.com/uploads/2011/01/IMG_0933-1600-150x150.jpg" /></a>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2011/01/IMG_0934-1600.jpg"><img alt="" class="img-gallery" src="https://ferdinandkeil.com/uploads/2011/01/IMG_0934-1600-150x150.jpg" /></a>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2011/01/IMG_0943-1600.jpg"><img alt="" class="img-gallery" src="https://ferdinandkeil.com/uploads/2011/01/IMG_0943-1600-150x150.jpg" /></a>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2011/01/ecc82_irf510_amp_v1_sch.png"><img alt="" class="img-gallery" src="https://ferdinandkeil.com/uploads/2011/01/ecc82_irf510_amp_v1_sch-150x150.png" /></a>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2011/01/ecc82_irf510_amp_v1_brd.png"><img alt="" class="img-gallery" src="https://ferdinandkeil.com/uploads/2011/01/ecc82_irf510_amp_v1_brd-150x150.png" /></a>
<p>Den Schaltplan und das Boardlayout veröffentliche ich hier unter der <a class="reference external" href="http://creativecommons.org/licenses/by-nc-sa/3.0/">CC
BY-NC-SA 3.0
Lizenz</a>. Jeder der
möchte kann den Verstärker gerne nachbauen. Als Gehäuse bieten sich das
<a class="reference external" href="http://www.pollin.de/shop/t/NjM4OTA5OTk-/Bauelemente/Gehaeuse/Kunststoff_Universalgehaeuse.html">Kunststoff-Universalgehäuse (Bestellnummer: 460
021)</a>
von <a class="reference external" href="http://pollin.de">Pollin</a> oder das <a class="reference external" href="http://www.reichelt.de/?ACTION=3;ARTICLE=21230;PROVID=2402">TEKO P1
Gehäuse</a>
von <a class="reference external" href="http://reichelt.de">Reichelt</a> an. Die Bohrungen auf der Platine
sind auch auf diese Gehäuse ausgelegt.</p>
<p>Download der Eagle-Dateien:</p>
<div class="line-block">
<div class="line"><br /></div>
</div>
<a href="https://ferdinandkeil.com/uploads/2011/01/ECC82-IRF510-Kopfhörerverst.zip"><i class="fa fa-floppy-o fa-2x" aria-hidden="true"></i> ECC82-IRF510-Kopfhörerverst.zip</a><hr class="docutils" />
<p><strong>Ergänzung 05. März 2012</strong>
Vor der Inbetriebnahme des Verstärkers muss der Ruhestrom durch die
zwei MOSFETs mit den zwei Trimmern eingestellt werden. Dabei muss der
Trimmer bei jedem MOSFET so abgeglichen werden, dass die Spannung am
Source-Pin des FET gerade 1/2 Vcc beträgt. Wird der Verstärker wie
vorgesehen mit 12 V betrieben muss die Spannung also 6 V betragen. Die
Leiterbahnen und Pads die mit den Source-Pins verbunden sind habe ich
in der folgenden Grafik markiert.
Viele weitere Informationen zu der Schaltung gibt es unter
<a class="reference external" href="http://diyaudioprojects.com/Solid/12AU7-IRF510-LM317-Headamp/">http://diyaudioprojects.com/Solid/12AU7-IRF510-LM317-Headamp/</a>. Dort
gibt es auch ein Forum mit einem Support Thread:
<a class="reference external" href="http://diyaudioprojects.com/Forum/viewtopic.php?f=10&t=1799">http://diyaudioprojects.com/Forum/viewtopic.php?f=10&t=1799</a>.</p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2011/01/ecc82_amp_messpunkte_bias.png"><img alt="image0" class="alignnone size-medium wp-image-631" src="https://ferdinandkeil.com/uploads/2011/01/ecc82_amp_messpunkte_bias-300x194.png" style="width: 300px; height: 194px;" /></a></p>
Windows 7 Netzwerkidentifizierung austricksen2011-01-05T18:53:00+01:002011-01-05T18:53:00+01:00ferdinandtag:ferdinandkeil.com,2011-01-05:/windows-7-netzwerkidentifizierung-austricksen.html<p>Um an meinem Arbeitsplatzrechner (Windows XP) per RDP auf mein Laptop
(Windows 7) zugreifen zu können habe ich die beiden Computer per
LAN-Kabel direkt verbunden. Nachdem ich die IP Adressen konfiguriert
hatte konnte ich die beiden PCs untereinander anpingen. Eine
RDP-Verbindung konnte ich trotzdem nicht aufbauen. Nachdem ich die
Firewall …</p><p>Um an meinem Arbeitsplatzrechner (Windows XP) per RDP auf mein Laptop
(Windows 7) zugreifen zu können habe ich die beiden Computer per
LAN-Kabel direkt verbunden. Nachdem ich die IP Adressen konfiguriert
hatte konnte ich die beiden PCs untereinander anpingen. Eine
RDP-Verbindung konnte ich trotzdem nicht aufbauen. Nachdem ich die
Firewall unter Windows 7 deaktiviert hatte funktionierte es. Also lag
das Problem dort, genauer in der Netzwerkidentifizierung die seit
Windows Vista integriert ist. Netzwerke werden anhand der MAC-Adresse
des Gateways unterschieden und in drei Kategorien aufgeteilt:</p>
<ul class="simple">
<li>Öffentliche Netzwerke: strenge Vorgaben für die Firewall, evtl.
gefährdete Dienste sind von außen nicht erreichbar (inklusive RDP).</li>
<li>Heimnetzwerke: alle Dienste sind von außen erreichbar.</li>
<li>Arbeitsplatznetzwerke: eine Stufe zwischen den beiden ersten.</li>
</ul>
<p>Wenn zwei Computer direkt verbunden werden ist in dem Netzwerk kein
Gateway vorhanden. Die Identifizierung des Netzwerk scheitert daher
und Windows ordnet es automatisch als Öffentliches Netzwerk ein.
Dieses Verhalten lässt sich jedoch nicht beeinflussen. Ohne die
Firewall für den jeweiligen Adapter zu deaktivieren ist in dieser
Konfiguration kein Zugriff per RDP möglich.
Oder doch? Konfiguriert man in den TCP/IP Einstellungen unter Windows
7 den XP-Rechner als Gateway (was natürlich Unsinn ist), wird der
Dialog zur Auswahl der "Netzwerkadresse" angezeigt und nachdem das
Netzwerk als Heimnetzwerk konfiguriert wurde funktioniert auch der
Zugriff per RDP. Solange die zwei Computer direkt verbunden sind wird
kein Gateway benötigt, daher stört es auch nicht wenn der angegebene
PC keine Gateway Funktionen bietet.</p>
<p>Im Ergebnis kann man so den Automatismus von Windows 7 bei der
Konfiguration der Netzwerkadresse beeinflussen ohne die Firewall zu
deaktivieren.</p>
Reparatur HP L1955 Monitor2010-12-25T20:50:00+01:002010-12-25T20:50:00+01:00ferdinandtag:ferdinandkeil.com,2010-12-25:/reparatur-hp-l1955-monitor.html<p>Vor kurzem bekam ich einen HP L1955 zum reparieren. Der Monitor war mit
einem Knall und einer kleinen Rauchwolke abgetreten. Ich schaltete den
Monitor ein und er blieb dunkel obwohl die Power LED leuchtete. Bei
genauerem Hinsehen zeigte sich jedoch, dass die Anzeige arbeitete. Die
Hintergrundbeleuchtung war jedoch ausgefallen, das …</p><p>Vor kurzem bekam ich einen HP L1955 zum reparieren. Der Monitor war mit
einem Knall und einer kleinen Rauchwolke abgetreten. Ich schaltete den
Monitor ein und er blieb dunkel obwohl die Power LED leuchtete. Bei
genauerem Hinsehen zeigte sich jedoch, dass die Anzeige arbeitete. Die
Hintergrundbeleuchtung war jedoch ausgefallen, das Bild konnte man nicht
erkennen. Da in dem Monitor 2 CCFL Röhren verbaut sind und der Ausfall
beider zur gleichen Zeit unwahrscheinlich war, tippte ich auf einen
Defekt im Netzteil. Und in der Tat befanden sich auf der Netzteil
Platine Rauchspuren und zwei angebrannte Transistoren.</p>
<p>Eine Google Recherche ergab, dass ein Ausfall des Netzteils für die
Hintergrundbeleuchtung bei diesem Modell ein Standardfehler ist. Bei
eBay gibt es Pakete die alle auszutauschenden Bauteile enthalten. Also
schnell ein solches geordert. Nur eine passende Picofuse musste ich
noch separat besorgen. Dann ging es an das Zerlegen des Monitors.</p>
<p><strong>Hinweis</strong>
Die Netzteilplatine ist <em>direkt</em> mit dem Stromnetz verbunden und führt
daher <em>potentiell tödliche Spannungen</em>. Arbeiten am Netzteil dürfen
nur durchgeführt werden wenn das Gerät vorher <em>vom Stromnetz getrennt</em>
wurde. Bevor am Gerät gearbeitet wird sollte man etwa 10 Minuten
warten damit sich die Kondensatoren auf der Platine komplett entladen
können.</p>
<p><strong>Schritt 1</strong></p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2010/12/IMG_0856-1024.jpg"><img alt="image0" src="https://ferdinandkeil.com/uploads/2010/12/IMG_0856-1024-300x199.jpg" style="width: 300px; height: 199px;" /></a></p>
<p>Zunächst müssen die Schrauben an der Seite gelöst werden. Diese befinden
sich hinter runden Aufklebern die einfach mit einem dünnen
Schraubenzieher/Messer gelöst werden. Die Verkleidung ist noch mit Clips
befestigt. Wenn die Schrauben raus sind, den Monitor mit dem Display
nach unten auf eine plane Oberfläche legen und die Verkleidung
entfernen.</p>
<p><strong>Schritt 2</strong></p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2010/12/IMG_0855-1024.jpg"><img alt="image1" src="https://ferdinandkeil.com/uploads/2010/12/IMG_0855-1024-300x199.jpg" style="width: 300px; height: 199px;" /></a></p>
<p>Nun müssen die Schrauben rund um den Metallkäfig gelöst werden.</p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2010/12/IMG_0852-1024.jpg"><img alt="image2" src="https://ferdinandkeil.com/uploads/2010/12/IMG_0852-1024-300x199.jpg" style="width: 300px; height: 199px;" /></a></p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2010/12/IMG_0853-1024.jpg"><img alt="image3" src="https://ferdinandkeil.com/uploads/2010/12/IMG_0853-1024-300x199.jpg" style="width: 300px; height: 199px;" /></a></p>
<p>Danach kann dieser abgenommen werden.</p>
<p><strong>Schritt 3</strong></p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2010/12/IMG_0850-1024.jpg"><img alt="image4" src="https://ferdinandkeil.com/uploads/2010/12/IMG_0850-1024-300x199.jpg" style="width: 300px; height: 199px;" /></a></p>
<p>Nun muss die Netzteilplatine demontiert werden. Dazu erst die Stecker
(im Bild gelb markiert) und danach die Schrauben (im Bild rot markiert)
lösen. Danach kann die Platine entfernt werden.</p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2010/12/IMG_0849-1024.jpg"><img alt="image5" src="https://ferdinandkeil.com/uploads/2010/12/IMG_0849-1024-300x199.jpg" style="width: 300px; height: 199px;" /></a></p>
<p><strong>Schritt 4</strong></p>
<p>Jetzt muss der Lötkolben angeheizt werden, denn die kaputten Komponenten
müssen raus. Wenn einer der markierten Transistoren einen Defekt
aufweist (Rauchspuren oder Kurzschluss), sollten alle markierten
Bauteile getauscht werden.</p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2010/12/IMG_0848-1024.jpg"><img alt="image6" src="https://ferdinandkeil.com/uploads/2010/12/IMG_0848-1024-300x199.jpg" style="width: 300px; height: 199px;" /></a></p>
<p>Sterbende FETs hinterlassen Rauchspuren, daher sollte die Platine noch
mit Isopropyl-Alkohol gereinigt werden. Auch nach dem Einlöten ist das
sinnvoll.</p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2010/12/IMG_0844-1024.jpg"><img alt="image7" src="https://ferdinandkeil.com/uploads/2010/12/IMG_0844-1024-300x199.jpg" style="width: 300px; height: 199px;" /></a></p>
<p>Auf der Unterseite sollten auch noch die Transistoren geprüft werden die
die FETs ansteuern, da auch diese beschädigt sein können. Bei mir war
dies nicht der Fall.</p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2010/12/IMG_0840.jpg"><img alt="image8" src="https://ferdinandkeil.com/uploads/2010/12/IMG_0840-1024-300x199.jpg" style="width: 300px; height: 199px;" /></a></p>
<p><strong>Schritt 5</strong></p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2010/12/IMG_0846-1024.jpg"><img alt="image9" src="https://ferdinandkeil.com/uploads/2010/12/IMG_0846-1024-300x199.jpg" style="width: 300px; height: 199px;" /></a></p>
<p>Nachdem die defekten Bauteile entfernt sind kann die Platine wieder
eingebaut und getestet werden. Wenn die Hintergrundbeleuchtung
funktioniert kann das Gerät wieder zusammengebaut werden.</p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2010/12/IMG_0857-1024.jpg"><img alt="image10" src="https://ferdinandkeil.com/uploads/2010/12/IMG_0857-1024-300x199.jpg" style="width: 300px; height: 199px;" /></a></p>
<p><strong>Update 11.10.2011:</strong>
Die Netzteilplatine des HP L1955 hat die Bezeichnung Benq
48.L1A02.A00. Bei eBay finden sich bei einer Suche nach der Platine
oder den Typbezeichnungen der defekten Transistoren (z.B. C5707 oder
FU9024N) Bauteilkits für die Reperatur des Geräts.</p>
Seagate DockStar - Original Firmware wiederherstellen2010-10-18T20:59:00+02:002010-10-18T20:59:00+02:00ferdinandtag:ferdinandkeil.com,2010-10-18:/seagate-dockstar-original-firmware-wiederherstellen.html<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2010/10/IMG_0416-1024.jpg"><img alt="image0" src="https://ferdinandkeil.com/uploads/2010/10/IMG_0416-1024-300x225.jpg" style="width: 300px; height: 225px;" /></a></p>
<p>Ich bin seit geraumer Zeit glücklicher Besitzer eines Seagate DockStar.
Zunächst hatte ich gemäß der Anleitung von <a class="reference external" href="http://www.cs.cmu.edu/~ecc/dockstar-howto.html">Eric
Cooper</a> OpenWRT auf
dem Gerät installiert. Einen UPnP AV Server hatte ich bereits in
Betrieb, dank DLNA Unterstützung funktionierte das auch mit der PS3. Als
ich dann allerdings einen Printerserver einrichten wollte …</p><p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2010/10/IMG_0416-1024.jpg"><img alt="image0" src="https://ferdinandkeil.com/uploads/2010/10/IMG_0416-1024-300x225.jpg" style="width: 300px; height: 225px;" /></a></p>
<p>Ich bin seit geraumer Zeit glücklicher Besitzer eines Seagate DockStar.
Zunächst hatte ich gemäß der Anleitung von <a class="reference external" href="http://www.cs.cmu.edu/~ecc/dockstar-howto.html">Eric
Cooper</a> OpenWRT auf
dem Gerät installiert. Einen UPnP AV Server hatte ich bereits in
Betrieb, dank DLNA Unterstützung funktionierte das auch mit der PS3. Als
ich dann allerdings einen Printerserver einrichten wollte stieß ich an
die Grenzen des Systems. Da Eric eigens einen Kernel kompiliert hat sind
die Standard OpenWRT Module nicht kompatibel. Um einen Drucker
anzuschließen hätte ich die notwendigen Module also selber kompilieren
müssen - DOH. In das Thema wollte ich mich wirklich nicht einarbeiten.</p>
<p>Also musste ein anderes Betriebssystem her. Schnell war klar, dass es
Debian werden würde.</p>
<p>Problem: um ein neues System zu installieren muss man entweder</p>
<ul class="simple">
<li>Zugriff per serieller Konsole auf das Gerät haben oder</li>
<li>die Original Firmware verwenden.</li>
</ul>
<p>Die zweite Variante fiel dank der OpenWRT Installation flach. Also
musste eine serielle Verbindung her. Nachdem ich endlich eine
Pfostenverbinder-Buchse mit 2mm Pinabstand bestellt hatte konnte ich ein
Adapterkabel basteln. Zur Sicherheit habe ich alle 10 Pins angeschlossen
- wer weiß ob nicht doch eine JTAG Session notwendig wird. Mit dem Kabel
und dem Bus Pirate im UART-Bridge Modus war das wiederherstellen der
Original Firmware kein Problem. Als nächstes wird Debian auf einen Stick
gepackt.</p>
<p>Links:</p>
<ul class="simple">
<li><a class="reference external" href="http://en.sourceforge.jp/projects/ttssh2/releases/">Tera Term</a> -
gutes Terminal Programm</li>
<li><a class="reference external" href="http://tftpd32.jounin.net/">tftpd32</a> - bringt einen TFTP und DHCP
Server mit</li>
<li><a class="reference external" href="http://plugapps.com/index.php5?title=Hardware:_Seagate_DockStar_Reflashing">Informationen zum
Flashen</a></li>
</ul>
<p><strong>Update 30.06.2011</strong>
Unter <a class="reference external" href="http://ferdinand-keil.de/2011/06/30/how-to-restore-a-locked-up-seagate-dockstar/">How to restore a locked up Seagate
Dockstar</a>
habe ich nun auch den Prozess zum Flashen des Bootloaders per JTAG
beschrieben. Wie der Bootloader überhaupt beschädigt wurde weiß ich
bis heute nicht.</p>
Humidor Lüfter - Dokumentation2010-03-08T20:54:00+01:002010-03-08T20:54:00+01:00ferdinandtag:ferdinandkeil.com,2010-03-08:/humidor-lufter-dokumentation.html<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2010/03/Bild-013_small.jpg"><img alt="Vorderseite" src="https://ferdinandkeil.com/uploads/2010/03/Bild-013_small-300x225.jpg" style="width: 300px; height: 225px;" /></a></p>
<p>Ich habe die Firmware und die Eagle Dateien für den Humidor Lüfter
online gestellt.
Alle wichtigen Informationen zu dem Projekt sind jetzt auf der Seite
<a class="reference external" href="/elektronik/humidor-lufter/">Humidor Lüfter</a> zu finden.</p>
USBtiny unter Linux2010-02-22T17:43:00+01:002010-02-22T17:43:00+01:00ferdinandtag:ferdinandkeil.com,2010-02-22:/usbtiny-unter-linux.html<p>Nachdem ich mittlerweile einen
<a class="reference external" href="http://www.mikrocontroller.net/articles/AVR-ISP-Stick">AVR-ISP-Stick</a>
von Daniel P. mein Eigen nenne habe ich auch diesen unter Linux in
Betrieb genommen. Auch hier war wieder das Problem, dass ohne udev-Regel
nur ROOT auf den ISP zugreifen konnte. Daher nun hier die Regel für den
Stick:</p>
<p>Datei: /etc/udev/rules.d/99-avrisp …</p><p>Nachdem ich mittlerweile einen
<a class="reference external" href="http://www.mikrocontroller.net/articles/AVR-ISP-Stick">AVR-ISP-Stick</a>
von Daniel P. mein Eigen nenne habe ich auch diesen unter Linux in
Betrieb genommen. Auch hier war wieder das Problem, dass ohne udev-Regel
nur ROOT auf den ISP zugreifen konnte. Daher nun hier die Regel für den
Stick:</p>
<p>Datei: /etc/udev/rules.d/99-avrisp.rules</p>
<div class="highlight"><pre><span></span># USBtiny
SYSFS{idVendor}=="1781", SYSFS{idProduct}=="0c9f", GROUP="%GROUP%", MODE="0660"
</pre></div>
<p>Eine udev-Regel für ein beliebiges Gerät zu schreiben ist nicht schwer.
Eine sehr gute Anleitung gibt es auf
<a class="reference external" href="http://wiki.ubuntuusers.de/udev">ubuntuusers.de</a>. Nachdem die Regel
erstellt wurde muss sie nur noch per</p>
<div class="highlight"><pre><span></span>sudo /etc/init.d/udev reload
<span class="c1"># alternativ</span>
sudo reload udev
</pre></div>
<p>geladen werden. Nun wird das Gerät
jedes mal für <tt class="docutils literal">%GROUP%</tt> erreichbar eingehängt.</p>
USBasp unter Ubuntu2010-01-03T20:39:00+01:002010-01-03T20:39:00+01:00ferdinandtag:ferdinandkeil.com,2010-01-03:/usbasp-unter-ubuntu.html<p>Der <a class="reference external" href="http://ferdinand-keil.de/2009/11/30/lv-usbasp-ist-fertig/">LV-USBasp</a>
funktioniert ohne Probleme unter Linux. avrdude bringt in der - für
Ubuntu 9.10 verfügbaren - Version 5.8 eingebaute Unterstützung für den
Programmer mit. Ich hatte jedoch das Problem, dass ich nur als ROOT auf
den Programmer zugreifen durfte. Der Fehler kam dadurch zustande, dass
udev unbekannte Geräte (also …</p><p>Der <a class="reference external" href="http://ferdinand-keil.de/2009/11/30/lv-usbasp-ist-fertig/">LV-USBasp</a>
funktioniert ohne Probleme unter Linux. avrdude bringt in der - für
Ubuntu 9.10 verfügbaren - Version 5.8 eingebaute Unterstützung für den
Programmer mit. Ich hatte jedoch das Problem, dass ich nur als ROOT auf
den Programmer zugreifen durfte. Der Fehler kam dadurch zustande, dass
udev unbekannte Geräte (also Geräte für die keine udev Regel existiert)
nur für ROOT sichtbar einhängt. Die Lösung zu dem Problem habe ich auf
<a class="reference external" href="http://www.mikrocontroller.net/topic/116724">mikrocontroller.net</a>
gefunden. So sieht jetzt meine udev Regel aus:</p>
<p>Datei: /etc/udev/rules.d/99-avrisp.rules</p>
<div class="highlight"><pre><span></span># Atmel AVR ISP mkII
SYSFS{idVendor}=="03eb", SYSFS{idProduct}=="2104", GROUP="%GROUP%", MODE="0660"
# usbprog bootloader
SYSFS{idVendor}=="1781", SYSFS{idProduct}=="0c62", GROUP="%GROUP%", MODE="0660"
# USBasp programmer
SYSFS{idVendor}=="16c0", SYSFS{idProduct}=="05dc", GROUP="%GROUP%", MODE="0660"
</pre></div>
<p><tt class="docutils literal">%GROUP%</tt> muss durch die entsprechende Gruppe ersetzt werden (bei
Ubuntu z.B. der Benutzername).</p>
LV-USBasp ist fertig2009-11-30T19:00:00+01:002009-11-30T19:00:00+01:00ferdinandtag:ferdinandkeil.com,2009-11-30:/lv-usbasp-ist-fertig.html<p>Am letzten Wochenende wurde es mal wieder Zeit ein wenig zu basteln.
Die Teile und die Platine für den LV-USBasp von Pawel Szramowski hatte
ich schon vor geraumer Zeit bestellt, jetzt ging es an den Aufbau.
Ich habe das ursprüngliche Layout so angepasst, dass die Platine in
ein TEKO Gehäuse …</p><p>Am letzten Wochenende wurde es mal wieder Zeit ein wenig zu basteln.
Die Teile und die Platine für den LV-USBasp von Pawel Szramowski hatte
ich schon vor geraumer Zeit bestellt, jetzt ging es an den Aufbau.
Ich habe das ursprüngliche Layout so angepasst, dass die Platine in
ein TEKO Gehäuse (Serie SOAP) von Reichelt montiert werden kann.
Außerdem konnte ich die verwendete SMD Sicherung nirgendwo auftreiben
und hab sie durch einen bedrahteten PolySwitch ersetzt. Ansonsten hat
sich nicht viel geändert. Das Gehäuse habe ich mit Feilen und einer
kleinen Säge angepasst.
Das Henne-Ei Problem habe ich mit einem Kabel für die parallele
Schnittstelle gelöst. Danach funktionierte der USBasp ohne Probleme.
Im Anhang die Eagle Dateien für das Projekt inklusive meiner
angepassten Version.</p>
<a href="https://ferdinandkeil.com/uploads/2009/11/LV-USBasp.zip"><i class="fa fa-floppy-o fa-2x" aria-hidden="true"></i> LV-USBasp.zip</a><p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2009/11/IMG_0467_edited.JPG"><img alt="LV-USBasp Gehäuse offen" class="img-gallery" src="https://ferdinandkeil.com/uploads/2009/11/IMG_0467_edited-150x150.jpg" style="width: 150px; height: 150px;" /></a>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2009/11/IMG_0463_edited.JPG"><img alt="LV-USBasp Außen" class="img-gallery" src="https://ferdinandkeil.com/uploads/2009/11/IMG_0463_edited-150x150.jpg" style="width: 150px; height: 150px;" /></a></p>
Humidor Lüfter - Update2009-10-08T02:14:00+02:002009-10-08T02:14:00+02:00ferdinandtag:ferdinandkeil.com,2009-10-08:/humidor-lufter-update.html<p>Bei der Schaltung sind mir noch ein paar Fehler aufgefallen, außerdem
fand ich das Platinenlayout letztendlich doch nicht schön.</p>
<p>Die Änderungen an der Schaltung:</p>
<ul class="simple">
<li>der MOSFET pull-up wurde korrekt an VCC angeschlossen</li>
<li>das Schieberegister hängt jetzt an normalen Ports</li>
<li>die Anschlüsse DISP0-1 und KEYPAD0-1 wurden umgelegt</li>
<li>die LED-Anzeigen haben keinen …</li></ul><p>Bei der Schaltung sind mir noch ein paar Fehler aufgefallen, außerdem
fand ich das Platinenlayout letztendlich doch nicht schön.</p>
<p>Die Änderungen an der Schaltung:</p>
<ul class="simple">
<li>der MOSFET pull-up wurde korrekt an VCC angeschlossen</li>
<li>das Schieberegister hängt jetzt an normalen Ports</li>
<li>die Anschlüsse DISP0-1 und KEYPAD0-1 wurden umgelegt</li>
<li>die LED-Anzeigen haben keinen Vorwiderstand mehr</li>
<li>am Schieberegister liegt OE nicht mehr auf LOW sondern an einem Port
(inkl. Pullup)</li>
</ul>
<p>Die meisten Änderungen waren für ein leichteres Routing. Ich konnte
die Schaltung so auf einer einseitigen Platine mit 2 Brücken
unterbringen. Auch die Größte der Platine ist geschrumpft.</p>
<p>Der Vorwiderstand für die LEDs war letztlich kein großer Verlust. Hat
nur Platz weggenommen und ist nicht schön zu löten. Stattdessen kann
die Anzeige jetzt per Output Enable Port und PWM gedimmt werden.
Leider hat der ATtiny keinen ADC, sonst könnte ich die Pulslänge noch
an die Batteriespannung anpassen und so versuchen die Helligkeit
konstant zu halten. Ist auf jeden Fall eine Idee für eine spätere
Version.</p>
<p>Auch der Verzicht auf die Unterstützung durch den eingebauten SPI Port
dürfte kein Problem bereiten. Der Prozessor wird bei der angedachten
Funktion kaum zu tun haben.</p>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2009/10/humidor_luefter_v4-schematic.png"><img alt="" class="img-gallery" src="https://ferdinandkeil.com/uploads/2009/10/humidor_luefter_v4-schematic-150x150.png" /></a>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2009/10/humidor_luefter_v4-board.png"><img alt="" class="img-gallery" src="https://ferdinandkeil.com/uploads/2009/10/humidor_luefter_v4-board-150x150.png" /></a>
Humidor Lüfter2009-09-23T16:49:00+02:002009-09-23T16:49:00+02:00ferdinandtag:ferdinandkeil.com,2009-09-23:/humidor-lufter.html<p>Mein letzter Post ist wieder fast einen Monat her, aber ich bin in der
Zwischenzeit nicht untätig gewesen. Das Hygrometer-Projekt liegt
erstmal auf Eis, vorerst habe ich noch ein paar kleinere Sachen
geplant.</p>
<p>Das erste kleinere Projekt ist ein Lüfter für meinen Humidor. Bei den
<a class="reference external" href="/nokia-display-teil-3">Experimenten mit den step-up-Wandlern</a>
hatte …</p><p>Mein letzter Post ist wieder fast einen Monat her, aber ich bin in der
Zwischenzeit nicht untätig gewesen. Das Hygrometer-Projekt liegt
erstmal auf Eis, vorerst habe ich noch ein paar kleinere Sachen
geplant.</p>
<p>Das erste kleinere Projekt ist ein Lüfter für meinen Humidor. Bei den
<a class="reference external" href="/nokia-display-teil-3">Experimenten mit den step-up-Wandlern</a>
hatte ich ja eine Version um 5V Lüfter mit 2 Batterien zu betreiben
erfolgreich getestet. Der Plan war jetzt, das ganze mit einer
Steuerung zu versehen, sodass der Lüfter in regelmäßigen Abständen
anläuft und die Luft im Humidor umwälzt. Meine Hoffnung ist, dass ich
dadurch eine gleichmäßigere Befeuchtung erreiche.</p>
<p>Die Idee war an sich simpel, allerdings nicht so ganz einfach
umzusetzen. Mein größtes Problem war das Schalten der Versorgung des
Spannungswandlers (würde ich nur den Ausgang schalten wären die Verluste
durch den im Leerlauf arbeitenden Wandler zu groß). Ein
Bipolartransistor kam nicht infrage, da ich aufgrund der sowieso schon
niedrigen Batteriespannung den Spannungsabfall am Übergang nicht
gebrauchen konnte. Blieben nur noch Mosfets. Die Zielvorgabe war
einfach: schaltet mit 3V durch, hat einen möglichst kleinen Ron und
Verfügbarkeit bei Reichelt. Vor allem die Verfügbarkeit stellte sich
schnell als problematisches Kriterium raus. Denn es gibt wohl für so
ziemlich jeden Anwendungsfall den passenden Transistor, nur halt nicht
bei jedem Händler. Und da ich nicht für einen Transistor eine Bestellung
beim großen C oder Farnell aufgeben wollte (von Mindestbestellwerten mal
abgesehen), musste ich halt etwas suchen. Meine Wahl ist letztlich auf
den <a class="reference external" href="http://search.datasheetcatalog.net/key/BSP171">BSP171</a> gefallen.
Ron ist mit 0,35 Ohm nicht optimal aber durchaus akzeptabel.</p>
<p>Das Drumherum war dann schnell gefunden: ein ATtiny2313 als
Schaltzentrale, zwei 7 Segment LED-Anzeigen und drei Taster. Das Board
habe ich mittlerweile auch fertig, jetzt muss ich nur noch die Teile
bestellen, prüfen ob die passen, ein paar Tests machen und dann die
Platinen ordern und bestücken.</p>
<p>An sich bin ich mit dem Layout ganz zufrieden. Auch wenn es
doppelseitig geworden ist, finde ich es so ganz übersichtlich. Und die
Mischbestückung ist Absicht: den 74HC595 habe ich noch als DIL auf
Lager und den ATtiny möchte ich gerne sockeln.</p>
<p>Sobald ich die fertige Platine getestet habe und der Code fertig ist
werde ich das hier als Projekt einstellen.</p>
<p>Außerdem habe ich noch die LV-USBasp Schaltung von Pawel Szramowski so
angepasst, dass sie mit Teilen von Reichelt gebaut werden kann. Die
Schaltung ist eine Abwandlung des AVR-ISP-Programmierers von <a class="reference external" href="http://www.fischl.de/usbasp/">Thomas
Fischl</a>.</p>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2009/09/humidor_luefter_v2-schematic.png"><img alt="" class="img-gallery" src="https://ferdinandkeil.com/uploads/2009/09/humidor_luefter_v2-schematic-150x150.png" /></a>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2009/09/humidor_luefter_v2-board_top.png"><img alt="" class="img-gallery" src="https://ferdinandkeil.com/uploads/2009/09/humidor_luefter_v2-board_top-150x150.png" /></a>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2009/09/humidor_luefter_v2-board_bottom.png"><img alt="" class="img-gallery" src="https://ferdinandkeil.com/uploads/2009/09/humidor_luefter_v2-board_bottom-150x150.png" /></a>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2009/09/lv_usbasp_edited-schematic.png"><img alt="" class="img-gallery" src="https://ferdinandkeil.com/uploads/2009/09/lv_usbasp_edited-schematic-150x150.png" /></a>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2009/09/lv_usbasp_edited-board.png"><img alt="" class="img-gallery" src="https://ferdinandkeil.com/uploads/2009/09/lv_usbasp_edited-board-150x150.png" /></a>
Erfahrungsbericht platinenbelichter.de2009-07-14T15:34:00+02:002009-07-14T15:34:00+02:00ferdinandtag:ferdinandkeil.com,2009-07-14:/erfahrungsbericht-platinenbelichter-de.html<p><a class="reference external" href="http://ferdinand-keil.de/2009/06/16/nokia-display-teil-2/">Wie bereits
berichtet</a>
hatte ich einige Platinen bei
<a class="reference external" href="http://platinenbelichter.de">platinenbelichter.de</a> zum Fertigen
gegeben. Bei der ersten Lieferung waren die Platinen leider nicht
gebohrt worden. Nachdem ich dies bemängelte bekam ich prompt einen
neuen Satz geschickt. Die Emails von Heinz (dem Platinenbelichter)
sind stets freundlich und man bekommt wirklich sehr schnell …</p><p><a class="reference external" href="http://ferdinand-keil.de/2009/06/16/nokia-display-teil-2/">Wie bereits
berichtet</a>
hatte ich einige Platinen bei
<a class="reference external" href="http://platinenbelichter.de">platinenbelichter.de</a> zum Fertigen
gegeben. Bei der ersten Lieferung waren die Platinen leider nicht
gebohrt worden. Nachdem ich dies bemängelte bekam ich prompt einen
neuen Satz geschickt. Die Emails von Heinz (dem Platinenbelichter)
sind stets freundlich und man bekommt wirklich sehr schnell eine
Antwort auf Fragen. Ich habe für 5 Platinen die auf Rohmaterial von
100x80mm gepasst haben inklusive Schneiden, Verzinnen, Bohren und
Versand nur knapp 10 € bezahlt. Das ist wirklich ein super Preis.</p>
<p>Am Wochenende habe ich dann auch den Großteil der Platinen bestückt
und konnte feststellen, dass die Qualität über jeden Zweifel erhaben
ist. Klar, Stoplack wäre nützlich gewesen, aber dank der Verzinnung
lassen sich die Platinen auch so super löten. Die Strukturen auf der
Platine sind sehr fein und exakt und ich gehe davon aus, dass auch
noch kleinere SMD Teile verwendet werden können (bei dieser Bestellung
war nichts kleiner als 0603 und SSOP).</p>
<p>Ich hatte leider noch Fehler im Layout der Schaltregler (unterbrochene
Ground-Fläche), daher die zwei Kabel auf den Platinen.</p>
<p><strong>Fazit:</strong>
Für kleinere Projekte die keine professionellen Platinen benötigen ist
platinenbelichter.de perfekt. Die Lieferzeiten sind gut (ca. 7 Tage)
und die Qualität der Platinen ist für den Preis sehr gut. Vias gibts
leider keine, die müsste man dann schon selber machen. Vor allem für
Prototypen die auf einseitige Platinen passen werde ich jetzt öfter
auf den Service zurückgreifen.</p>
<p>Sobald ich einen passenden Draht zum Löten von Vias gefunden habe
werde ich auch die doppelseitigen Platinen mal testen und dann hier
berichten.</p>
<p>Bilder von den Platinen</p>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2009/07/IMG_0259_SMALL.jpg"><img alt="" class="img-gallery" src="https://ferdinandkeil.com/uploads/2009/07/IMG_0259_SMALL-150x150.jpg" /></a>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2009/07/IMG_0255_SMALL.jpg"><img alt="" class="img-gallery" src="https://ferdinandkeil.com/uploads/2009/07/IMG_0255_SMALL-150x150.jpg" /></a>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2009/07/IMG_0256_SMALL.jpg"><img alt="" class="img-gallery" src="https://ferdinandkeil.com/uploads/2009/07/IMG_0256_SMALL-150x150.jpg" /></a>
<a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2009/07/IMG_0257_SMALL.jpg"><img alt="" class="img-gallery" src="https://ferdinandkeil.com/uploads/2009/07/IMG_0257_SMALL-150x150.jpg" /></a>
EeePC Tastatur reparieren2009-06-25T18:51:00+02:002009-06-25T18:51:00+02:00ferdinandtag:ferdinandkeil.com,2009-06-25:/eeepc-tastatur-reparieren.html<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2009/06/DSC00974.JPG"><img alt="EeePC Reperatur - Reinigungsmittel" class="alignnone size-medium wp-image-174" src="https://ferdinandkeil.com/uploads/2009/06/DSC00974-300x225.jpg" style="width: 300px; height: 225px;" /></a>
Vor kurzem war mir beim reinigen meines EeePC 700 Flüssigkeit in die
Tastatur geraten. Das führte letztlich dazu, dass die meisten Tasten
nicht mehr funktionierten.</p>
<p>Da ich keine neue Tastatur kaufen wollte (es gibt auch gar keine
deutsche Version als Ersatzteil) habe ich die kaputte zerlegt und
gereinigt. Jetzt funktioniert …</p><p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2009/06/DSC00974.JPG"><img alt="EeePC Reperatur - Reinigungsmittel" class="alignnone size-medium wp-image-174" src="https://ferdinandkeil.com/uploads/2009/06/DSC00974-300x225.jpg" style="width: 300px; height: 225px;" /></a>
Vor kurzem war mir beim reinigen meines EeePC 700 Flüssigkeit in die
Tastatur geraten. Das führte letztlich dazu, dass die meisten Tasten
nicht mehr funktionierten.</p>
<p>Da ich keine neue Tastatur kaufen wollte (es gibt auch gar keine
deutsche Version als Ersatzteil) habe ich die kaputte zerlegt und
gereinigt. Jetzt funktioniert sie wieder einwandfrei.</p>
<p>Falls jemand ein ähnliches Problem hat, so habe ich es gemacht:</p>
<p><strong>Schritt 1:</strong>
Zunächst muss die Tastatur ausgebaut werden. Dazu müssen die 3
Haltepunkte oberhalb der Tastatur gelöst werden. Danach kann die
Tastatur nach vorne weggeklappt werden. Sie ist jetzt noch mit einem
Flex-Kabel mit dem Mainboard verbunden. Dieses muss noch gelöst
werden. Dazu müssen am Stecker zwei Plastiknasen Richtung Bildschirm
geschoben werden. Danach kann die Tastatur entnommen werden.</p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2009/06/DSC00970_edited.JPG"><img alt="EeePC Reperatur - Haltepunkte und Flex-Buchse" class="alignnone size-medium wp-image-179" src="https://ferdinandkeil.com/uploads/2009/06/DSC00970_edited-300x225.jpg" style="width: 300px; height: 225px;" /></a> <a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2009/06/DSC00971_edited.JPG"><img alt="EeePC Reperatur - Flex-Buchse" class="alignnone size-medium wp-image-182" src="https://ferdinandkeil.com/uploads/2009/06/DSC00971_edited-300x225.jpg" style="width: 300px; height: 225px;" /></a></p>
<p><strong>Schritt 2:</strong>
Ist die Tastatur ausgebaut, fängt die eigentliche Arbeit an. Die
Tasten müssen einzeln entfernt werden. Das geht am besten mit einem
kleinen Schraubenzieher und von der Unterseite der Tastatur. Dort ist
jede Taste (bis auf Leertaste, Enter und Right-Shift) mit zwei Clips
festgemacht. Diese müssen gelöst werden damit sich die Taste abnehmen
lässt. Bei Leertaste, Enter und Right-Shift ist es etwas fummelig, da
diese Tasten noch mit einem Metall-Bügel befestigt sind. Sobald alle
Tasten entfernt worden sind, kann die schwarze Folie mit den
Gummi-Noppen entfernt werden. Jetzt sind die eigentlichen Kontakte
sichtbar: eine billige Folie mit je zwei Kohlekontakten. Diese sind
sehr schmutzempfindlich und müssen von allem Dreck sorgfältig
gereinigt werden.</p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2009/06/DSC00976.JPG"><img alt="EeePC Reperatur - Gummimatte" class="alignnone size-medium wp-image-175" src="https://ferdinandkeil.com/uploads/2009/06/DSC00976-300x225.jpg" style="width: 300px; height: 225px;" /></a> <a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2009/06/DSC00972.JPG"><img alt="EeePC Reperatur - Kontaktfolie" class="alignnone size-medium wp-image-172" src="https://ferdinandkeil.com/uploads/2009/06/DSC00972-300x225.jpg" style="width: 300px; height: 225px;" /></a></p>
<p><strong>Schritt 3:</strong>
Die Kontaktfolie muss noch von der Basisplatte gelöst werden. Sie ist
allerdings an zwei Punkten verschweißt. Um an die Kontakte zu kommen
müssen diese zwei Punkte vorsichtig mit einem Messer aufgeschnitten
werden. Ich habe sie nachher nicht mehr zusammengeklebt, die Tastatur
funktioniert trotzdem.</p>
<p>Jetzt geht es an die Reinigung. Ich habe dafür 100%igen
Isopropyl-Alkohol aus der Apotheke verwendet. Davon kosten 100ml keine
1,50 €. Ich habe jeden Kontakt einzeln mit einem Wattestäbchen
gereinigt. Dabei muss man aufpassen, das man die einmal gereinigten
Kontakte nicht mehr berührt, sonst war die Arbeit umsonst. Eine
saugfähige Unterlage (bei mir Zeitung) und Taschentücher sind
ebenfalls hilfreich.</p>
<p>Die Kontakte am Flex-Kabel sollten ebenfalls gereinigt werden.</p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2009/06/DSC00973_edited.JPG"><img alt="EeePC Reperatur - Kontaktfolie aufgeklappt" class="alignnone size-medium wp-image-173" src="https://ferdinandkeil.com/uploads/2009/06/DSC00973_edited-300x225.jpg" style="width: 300px; height: 225px;" /></a></p>
<p><strong>Schritt 4:</strong>
Nachdem die Folie komplett gereinigt wurde (die transparente
Zwischenfolie nicht vergessen), kann die Tastatur wieder
zusammengebaut werden. Dazu erst die Kontaktfolie wieder auf die
Basisplatte kleben - dabei muss man sorgfältig sein, sonst passt sie
nicht richtig. Danach kann die schwarze Folie mit den Gummi-Noppen
darauf gelegt werden. Nun fehlen nur noch die Tasten. Beim Einsetzen
sollte man vorsichtig umgehen, damit man die Halterungen in der dünnen
Basisplatte nicht verbiegt. Bei den Tasten mit den Metallbügeln ist es
hilfreich diesen und die weißen Scharniere von der Taste zu entfernen,
einzusetzen und dann die Taste drauf zusetzen. Hier dann auch noch ein
Bild von der Originalbelegung. Hilft enorm beim Zusammenbau.</p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2009/06/DSC00967_edited.JPG"><img alt="EeePC Reperatur - Tastenbelegung" class="alignnone size-medium wp-image-180" src="https://ferdinandkeil.com/uploads/2009/06/DSC00967_edited-300x113.jpg" style="width: 300px; height: 113px;" /></a> <a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2009/06/DSC00977.JPG"><img alt="EeePC Reperatur - Tasten einfügen" class="alignnone size-medium wp-image-176" src="https://ferdinandkeil.com/uploads/2009/06/DSC00977-300x225.jpg" style="width: 300px; height: 225px;" /></a></p>
<p><strong>Schritt 5:</strong>
Jetzt muss die Tastatur nur noch wieder angeschlossen und eingebaut
werden. Dazu muss das Flex-Kabel in den Stecker auf dem Mainboard
geführt werden und die Platiknasen wieder zurückgeschoben werden. Ist
das Kabel fest kann die Tastatur unten eingesetzt und dann oben
eingerastet werden.</p>
<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2009/06/DSC00978_edited.JPG"><img alt="EeePC Reperatur - Flex-Kabel" class="alignnone size-medium wp-image-177" src="https://ferdinandkeil.com/uploads/2009/06/DSC00978_edited-300x225.jpg" style="width: 300px; height: 225px;" /></a></p>
<p><em>Anmerkung:</em>
Ich übernehme natürlich keinerlei Garantie. Bei mir hat diese Methode
wunderbar funktioniert, aber das muss ja nicht immer so sein. Ich rate
allerdings davon ab, irgendwas anderes als reinen Alkohol zum Reinigen
zu verwenden: es besteht die Gefahr, dass sich bei anderen
Lösungsmitteln die Kontaktpunkte selbst auflösen oder Rückstände
zurückbleiben.</p>
Arduino als Webserver2009-06-20T21:30:00+02:002009-06-20T21:30:00+02:00ferdinandtag:ferdinandkeil.com,2009-06-20:/arduino-als-webserver.html<p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2009/06/DSC00968.JPG"><img alt="Arduino als Webserver Aufbau" src="https://ferdinandkeil.com/uploads/2009/06/DSC00968-300x225.jpg" style="width: 300px; height: 225px;" /></a> <a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2009/06/Arduino-EtherShield-SHT11-screenshot.png"><img alt="SHT11 im Netz - Browser" src="https://ferdinandkeil.com/uploads/2009/06/Arduino-EtherShield-SHT11-screenshot-300x128.png" style="width: 300px; height: 128px;" /></a></p>
<p>Da ich jetzt glücklicher Besitzer eines EtherShields und eines
SHT11-Sensors von <a class="reference external" href="http://nuelectronics.com">nuelectronics</a> bin
konnte ich erste Versuche mit dem Arduino im Netz starten.</p>
<p>Was natürlich auf der Hand lag war den SHT11 über den Arduino online
zu bringen. Ich habe dabei auf der
<a class="reference external" href="http://www.nuelectronics.com/download/projects/sht10_float.pde">SHT1X-Sketch</a>
und dem Webserver Beispiel aus der …</p><p><a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2009/06/DSC00968.JPG"><img alt="Arduino als Webserver Aufbau" src="https://ferdinandkeil.com/uploads/2009/06/DSC00968-300x225.jpg" style="width: 300px; height: 225px;" /></a> <a class="reference external image-reference" href="https://ferdinandkeil.com/uploads/2009/06/Arduino-EtherShield-SHT11-screenshot.png"><img alt="SHT11 im Netz - Browser" src="https://ferdinandkeil.com/uploads/2009/06/Arduino-EtherShield-SHT11-screenshot-300x128.png" style="width: 300px; height: 128px;" /></a></p>
<p>Da ich jetzt glücklicher Besitzer eines EtherShields und eines
SHT11-Sensors von <a class="reference external" href="http://nuelectronics.com">nuelectronics</a> bin
konnte ich erste Versuche mit dem Arduino im Netz starten.</p>
<p>Was natürlich auf der Hand lag war den SHT11 über den Arduino online
zu bringen. Ich habe dabei auf der
<a class="reference external" href="http://www.nuelectronics.com/download/projects/sht10_float.pde">SHT1X-Sketch</a>
und dem Webserver Beispiel aus der <a class="reference external" href="http://www.nuelectronics.com/download/projects/etherShield.zip">EtherShield
Library</a>
aufgebaut (beides auch von nuelectronics). Um eine Seite mit den Daten
vom SHT11 über den Webserver auszugeben habe ich gerade mal einen
Nachmittag gebraucht. Schön, wie einfach sowas gehen kann.</p>
<p>Mal schauen was mir als nächstes einfällt für den EtherShield.</p>
<p>Die Sketch kann runtergeladen werden.</p>
<div class="line-block">
<div class="line"><br /></div>
</div>
<a href="https://ferdinandkeil.com/uploads/2009/06/sketch_090620a.pde"><i class="fa fa-floppy-o fa-2x" aria-hidden="true"></i> SHT11 im Netz</a> (die oben genannte Library ist für die Sketch erforderlich)LCD Display und IR-Empfänger2008-02-08T23:34:00+01:002008-02-08T23:34:00+01:00ferdinandtag:ferdinandkeil.com,2008-02-08:/lcd-display-und-ir-empfanger.html<p>Nachdem ich heute und gestern dran gebastelt hab, läuft jetzt lirc und
lcd4linux. Alles beides wunderbare Programme, aber etwas umständlich
in der Handhabe.</p>
<p>lirc unter Xubuntu oder Ubuntu zu installieren ist extrem aufwändig,
da die nötigen Kernelmodule selber kompiliert werden müssen. Geholfen
hat mir <a class="reference external" href="http://ubuntuforums.org/showthread.php?t=30612">diese
Anleitung</a>. Ich
habe allerdings nicht …</p><p>Nachdem ich heute und gestern dran gebastelt hab, läuft jetzt lirc und
lcd4linux. Alles beides wunderbare Programme, aber etwas umständlich
in der Handhabe.</p>
<p>lirc unter Xubuntu oder Ubuntu zu installieren ist extrem aufwändig,
da die nötigen Kernelmodule selber kompiliert werden müssen. Geholfen
hat mir <a class="reference external" href="http://ubuntuforums.org/showthread.php?t=30612">diese
Anleitung</a>. Ich
habe allerdings nicht die Kernelquellen sondern nur die Header
gebraucht. Macht die Sache um einiges einfacher.</p>
<p>Bei lcd4linux war eine Stolperfalle, dass die Module parport,
parport_pc und ppdev geladen sein müssen und die Rechte für
/dev/parport0 so gesetzt sind, dass der entsprechende Nutzer zugreifen
kann. Ich hab ein 40x2 Display und dafür <a class="reference external" href="https://ferdinandkeil.com/uploads/2008/02/lcd4linux.txt">diese
Konfiguration</a>.</p>
<p>So, jetzt ist es geschafft und ich kann meinen PC als MP3 Player
verwenden :)</p>