tag:blogger.com,1999:blog-19609446725117906912024-03-13T17:08:56.192-07:00Arnout's blogarre234http://www.blogger.com/profile/04807961375666237936noreply@blogger.comBlogger3125tag:blogger.com,1999:blog-1960944672511790691.post-35884396669943577412019-03-21T12:54:00.003-07:002019-03-21T12:54:53.196-07:00Recovering data from a corrupted SD card with Linux<h2>
1.Introduction</h2>
<br />
<a href="https://1.bp.blogspot.com/-TD3bQlryjlc/XHv8s17K9oI/AAAAAAAABn0/Z_YaNstFWBsc0QRV_d7RLknibTK_EjoYQCLcBGAs/s1600/Capture.PNG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="142" data-original-width="141" src="https://1.bp.blogspot.com/-TD3bQlryjlc/XHv8s17K9oI/AAAAAAAABn0/Z_YaNstFWBsc0QRV_d7RLknibTK_EjoYQCLcBGAs/s1600/Capture.PNG" /></a>So the other day, someone asked me to have a look at their SD card. It had thousands of images on it from their holiday trip, but the card somehow got corrupted. It did not even show up anymore in windows when plugging in.. I said I'd quickly try to plug it in linux, and see what happened.<br />
<br />
Eventually <b>I managed to get 30GB out of the 64GB back</b> with the help of <b>photorec </b>and a <b>kernel driver patch</b>!<br />
<br />
I thought I'd share some of my findings of how SD cards work and how I managed to do this recovery.<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<h2>
2.Some background reading on SD cards and corruption</h2>
<br />
<span style="font-family: inherit;">(Feel free to skip this section and go directly to the Linux part. Couldn't resist given some background:)</span><br />
<span style="font-family: inherit;"><br /></span>
<br />
<h3>
<span style="font-family: inherit;">2.1 SD card background</span></h3>
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">SD cards, just like SSDs, consist out of some form of NAND flash, and a "controller" chip to talk the SD protocol to a PC, and interface with the flash and to "maintain it". NAND flash is increasibly cheap to make, but (especially MLC/TLC/..) has serious limitiations like that you can only write a single spot 1000 times and that you regularly have to reread sections to avoid them from going bad. The controller hence tries to be clever, and tries to use the NAND flash as optimally as possible.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">How well it succeeds in doing this, typically depends on two things:</span><br />
<span style="font-family: inherit;"> - The quality of the controller (and its firmware)</span><br />
<span style="font-family: inherit;"> - How the card is being used (how much data is written to it)</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;"><img alt="Afbeeldingsresultaat voor sd card controller sandisk" height="150" src="https://farm5.static.flickr.com/4073/4796907021_5dfcf240ed_b.jpg" width="200" /></span><br />
<span style="font-family: inherit;"> (An example of someone who opened up the card. The NAND flash below and controller above are visible.)</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">SSDs actually support stuff like TRIM, to tell the controller which parts of the "virtual drive" are actually not used anymore, and hence can be used for the wear-leveling pool of the controller. SD cards typically don't have this feature; and hence once you write you card full once, wear-leveling is going to have to move a lot of data around very quickly, reducing the lifetime of your card very quickly.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">Anyway, lots more to be said about this topic, but for this post, I'll focus a bit on what happens when stuff goes bad.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit; font-size: x-small;">(If you are interested further in tearing down these things and getting to the bottom of them, I really also recommend checking out the post from <i>bunnie</i>: <a href="https://www.bunniestudios.com/blog/?p=3554">https://www.bunniestudios.com/blog/?p=3554</a> - <a href="https://youtu.be/r3GDPwIuRK">https://youtu.be/r3GDPwIuRK</a>I ) </span><br />
<span style="font-family: inherit; font-size: x-small;"><br /></span>
<span style="font-family: inherit; font-size: x-small;"><br /></span>
<br />
<h4>
<span style="font-family: inherit;">2.1.1 Corruption in SD cards and recovery scenarios</span></h4>
<div>
<span style="font-family: inherit;"><br /></span></div>
<span style="font-family: inherit;">If the NAND flash starts failing (because it was written to too much by the controller (either because it was a stupid controller, or the controller had no choice due to usage)), the best case scenario is that the controller detects this. In fact, it typically will detect "bad blocks", which will become more and more common over time, and tries to avoid those sections in the future. If enough error correction was used, the data in the newly bad block might be recoverable, but otherwise the data is lost forever.</span><br />
<span style="font-family: inherit;"><br /></span>
<a href="about:invalid#zClosurez" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"></a><span style="font-family: inherit;">Controllers will typically try to avoid too much "damage" or dataloss on a card, by forcably putting the card in permanent read-only mode. Whatever data was lost will stay lost, but at more data writes (and wearleveling) are halted to prevent further harm.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">I have seriously had already 2 SD cards and 1 USB stick going permanent read-only like this.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">If the card does not prevent corruption soon enough, and corruption occurs, there are a few places where it can happen:</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">- The "controller data" (which keeps track of which data is where in NAND (since data is moved around constantly for wearleveling purposes))</span><br />
<span style="font-family: inherit;">- Criticial filesystem data (e.g. for FAT, the FAT table)</span><br />
<span style="font-family: inherit;">- Actual data (if some JPEGs are stored, parts of them might be bad)</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">The second two cases are pretty much the same stuff as you could have on a regular magnetic drive. The classic recovery tools can help you out. You can still try to take a byte-per-byte backup first, and analyze data from there.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">In the first case however is by far the worst. If the controller does not know which part of the NAND maps to what anymore, it might just give up altogether, and not even show up as an SD card anymore (e.g. not respond to SD card commands). Perhaps it will still respond for specific regions, or it might just show the regions as corrupt. All of this is guess work, and fully SD-card specific.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">The typical "recovery" scenario in this case, is to actually physically open up the card, and extract or directly probe the NAND chip, to get the raw data out of it. What is corrupt will still be corrupt, but at least you will get all the bytes out of the chip that were still there. Also recovering a "linear" disk out of the data is not trivial, since you need the controller data for that, which may be corrupt in the first place. Companies offer this kind of service, but it is not cheap, and still does not guarentee full data recovery obviously</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;"> </span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-PWbX-BsQ5Mc/XHv78LnlIQI/AAAAAAAABnk/7mKC4NYUuhMiL-sS9AvgLX5WfO9_Jl1HgCLcBGAs/s1600/DSC_0263-300x169.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: inherit;"><img border="0" data-original-height="169" data-original-width="300" src="https://4.bp.blogspot.com/-PWbX-BsQ5Mc/XHv78LnlIQI/AAAAAAAABnk/7mKC4NYUuhMiL-sS9AvgLX5WfO9_Jl1HgCLcBGAs/s1600/DSC_0263-300x169.jpg" /></span></a></div>
<span style="font-family: inherit;">An example of how the NAND flash in an SD card can be interfaced to directly (a commercial service offered by companies).</span><br />
<div>
<br /></div>
<br />
<br />
<h2>
3. A linux recovery attempt</h2>
<div>
<br /></div>
So, given how bad stuff might be, plugging the card into linux could show up a number of things:<br />
<br />
- Either nothing would happen (meaning the controller would fully have given up)<br />
- The controller would still communicate a bit, but fail to respond to certain commands <====<br />
- The controller would show the full drive, but its data might be a bit corrupt.<br />
<br />
Turned out to the be second case: <b>The SD card would not reply to commands to retrieve data from certain regions, but would reply for others. </b><br />
<br />
Since the MBR was still intact, linux correctly recognized the data partition. However, the FAT table was corrupt, and when trying to read raw data from the drive, the kernel would stall for long periods of time before even responding to a control+c / sigkill<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-bU9xES3mYFI/XJPoM639c5I/AAAAAAAABoA/poXX5f2pU9sg6Tt_TQkm4f0hkyZKNj2sACLcBGAs/s1600/sdcardhang.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="96" data-original-width="457" height="67" src="https://1.bp.blogspot.com/-bU9xES3mYFI/XJPoM639c5I/AAAAAAAABoA/poXX5f2pU9sg6Tt_TQkm4f0hkyZKNj2sACLcBGAs/s320/sdcardhang.png" width="320" /></a></div>
<br />
<br />
Experimentally trying out different regions to start with, I managed to recover gigabytes of data at over 10MB/s, but eventually the transfer would always bump into a "bad" region and slow down to mere bytes per second.<br />
<br />
Aside form the fact that it was super slow, there -was- data coming out of it. However, without a FAT, there was no way of knowing what was actually part of a file and what not. Photorec to the rescue!<br />
<br />
<br />
<h4>
3.1 Photorec to the rescue</h4>
<div>
<br /></div>
Photorec (https://www.cgsecurity.org/wiki/PhotoRec - also an official debian package for example) is an awesome piece of software. It simply ignores a filesystem, and tries to recover files based on their header signature. As you could have guessed, it certainly can recover pictures.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-ZvBv8aaXDb8/XJPov1SyLpI/AAAAAAAABoI/2FzDPMSasNkX0XJ3NrT2ly9xMNLUu5VYQCLcBGAs/s1600/photorec.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="336" data-original-width="550" height="195" src="https://3.bp.blogspot.com/-ZvBv8aaXDb8/XJPov1SyLpI/AAAAAAAABoI/2FzDPMSasNkX0XJ3NrT2ly9xMNLUu5VYQCLcBGAs/s320/photorec.PNG" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-tYXIwARVNuw/XJPpRKVT6BI/AAAAAAAABoU/T-ncQk1hbdMl6tH57P68XKM-b6D923o6gCLcBGAs/s1600/photorec2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="337" data-original-width="623" height="173" src="https://3.bp.blogspot.com/-tYXIwARVNuw/XJPpRKVT6BI/AAAAAAAABoU/T-ncQk1hbdMl6tH57P68XKM-b6D923o6gCLcBGAs/s320/photorec2.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
My very first run immediately turned up some pictures already! Also analyzing the few gigabytes of data that were quickly retrievable were quickly parsed using a loopback device: I first made a fast dd-copy in a region the SD card still dumped data quickly to a file, and then mounted it as virtual device for photorec to use:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-bYctO9oNiuE/XJPrlrDYZmI/AAAAAAAABog/jWNe-8rwBuIq6OyUCnLpe2bK4waFpo_egCLcBGAs/s1600/losetup.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="724" height="107" src="https://4.bp.blogspot.com/-bYctO9oNiuE/XJPrlrDYZmI/AAAAAAAABog/jWNe-8rwBuIq6OyUCnLpe2bK4waFpo_egCLcBGAs/s640/losetup.PNG" width="640" /></a></div>
<br />
<br />
<br />
This was already quite a good success (I managed to recover some 4GB this way), but by far the biggest part of the drive (the other 60GB) was littered with "slow sections". This was too much data to just ignore. <b>However, the estimated time to go through the entire drive was more than 100 hours. </b><br />
<br />
I then turned my attention to the linux kernel. Trying to figure out -why- the kernel slowed down so hard, and seeing if I could not tweak some sort of timeout in the kernel to speed up the process<br />
<br />
<br />
<h4>
3.2 The linux kernel SD card reader driver</h4>
<div>
<br /></div>
lsusb and lsmod quickly showed which driver I was using for the SD card reader: <b>rtsx_usb_sdmmc</b><br />
<br />
A quick inspection of the <a href="https://elixir.bootlin.com/linux/v4.20.13/source/drivers/mmc/host/rtsx_usb_sdmmc.c">code </a>showed that the driver supports dyndbg. Hence, we can simply enable some more verbose debugging in dmesg with the simple command:<br />
<br />
<br />
<br />
<div class="MsoNormal" style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">
</div>
<br />
<div style="-webkit-text-stroke-width: 0px; background: rgb(255, 255, 255); border: solid gray; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; orphans: 2; overflow: auto; padding: 0.2em 0.6em; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; width: auto; word-spacing: 0px;">
<pre style="line-height: 16.25px; margin: 0px;"><a href="about:invalid#zClosurez" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"></a># echo "module rtsx_usb_sdmmc +p" > /sys/kernel/debug/dynamic_debug/control
</pre>
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="about:invalid#zClosurez" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"></a></div>
This showed output like:<br />
<br />
<br />
<div style="background: rgb(255, 255, 255); border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><div style="font-family: "Times New Roman"; white-space: normal;">
<span style="font-size: x-small;"><span style="color: #666666;"> rtsx_usb_sdmmc rtsx_usb_sdmmc.0.auto: sdmmc_request</span></span></div>
<div style="font-family: "Times New Roman"; white-space: normal;">
<span style="color: #666666; font-size: x-small;"> rtsx_usb_sdmmc rtsx_usb_sdmmc.0.auto: sd_send_cmd_get_rsp: SD/MMC CMD 13, arg = 0xe6240000</span></div>
<div style="font-family: "Times New Roman"; white-space: normal;">
<span style="color: #666666; font-size: x-small;"> rtsx_usb_sdmmc rtsx_usb_sdmmc.0.auto: cmd->resp[0] = 0x00000900</span></div>
<div style="font-family: "Times New Roman"; white-space: normal;">
<span style="color: #666666; font-size: x-small;"> rtsx_usb_sdmmc rtsx_usb_sdmmc.0.auto: sdmmc_request</span></div>
<div style="font-family: "Times New Roman"; white-space: normal;">
<span style="color: #666666; font-size: x-small;"> rtsx_usb_sdmmc rtsx_usb_sdmmc.0.auto: sd_send_cmd_get_rsp: SD/MMC CMD 13, arg = 0xe6240000</span></div>
<div style="font-family: "Times New Roman"; white-space: normal;">
<span style="color: #666666; font-size: x-small;"> rtsx_usb_sdmmc rtsx_usb_sdmmc.0.auto: cmd->resp[0] = 0x00000900</span></div>
<div style="font-family: "Times New Roman"; white-space: normal;">
<span style="font-size: x-small;"><span style="color: #666666;"> rtsx_usb_sdmmc rtsx_usb_sdmmc.0.auto: sdmmc_request</span></span></div>
<div style="font-family: "Times New Roman"; white-space: normal;">
<span style="color: #666666; font-size: x-small;"> rtsx_usb_sdmmc rtsx_usb_sdmmc.0.auto: sd_send_cmd_get_rsp: SD/MMC CMD 13, arg = 0xe6240000</span></div>
<div style="font-family: "Times New Roman"; white-space: normal;">
<span style="color: #666666; font-size: x-small;"> rtsx_usb_sdmmc rtsx_usb_sdmmc.0.auto: cmd->resp[0] = 0x00000900</span></div>
<div style="font-family: "Times New Roman"; white-space: normal;">
<span style="color: #666666; font-size: x-small;"> rtsx_usb_sdmmc rtsx_usb_sdmmc.0.auto: sdmmc_request</span></div>
<div style="font-family: "Times New Roman"; white-space: normal;">
<span style="color: #666666; font-size: x-small;"> rtsx_usb_sdmmc rtsx_usb_sdmmc.0.auto: sd_send_cmd_get_rsp: SD/MMC CMD 13, arg = 0xe6240000</span></div>
</pre>
<div>
<br /></div>
</div>
<br />
<br />
By looking at the logging timestamps, it could be seen how sometimes read commands could take longer than 10 seconds before going into timeout! Surely this could be done better.<br />
<br />
After a bit of looking, I found the cause:<br />
<br />
<div style="background: rgb(255, 255, 255); border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"></pre>
<pre style="line-height: 16.25px;"><span style="font-family: "times new roman";"><span style="white-space: normal;">--- a/drivers/mmc/host/rtsx_usb_sdmmc.c</span></span>
<span style="font-family: "times new roman";"><span style="white-space: normal;">+++ b/drivers/mmc/host/rtsx_usb_sdmmc.c</span></span>
<span style="font-family: "times new roman";"><span style="white-space: normal;">@@ -530,7 +530,7 @@ static int sd_rw_multi(struct rtsx_usb_sdmmc *host, struct mmc_request *mrq)</span></span>
<span style="font-family: "times new roman";"><span style="white-space: normal;"> pipe = usb_sndbulkpipe(ucr->pusb_dev, EP_BULK_OUT);</span></span>
<span style="font-family: "times new roman";"><span style="white-space: normal;"> err = rtsx_usb_transfer_data(ucr, pipe, data->sg, data_len,</span></span>
<span style="font-family: "times new roman";"><span style="white-space: normal;">- data->sg_len, NULL, <b><span style="color: red;">10000</span></b>);</span></span>
<span style="font-family: "times new roman";"><span style="white-space: normal;">+ data->sg_len, NULL, <b><span style="color: #38761d;">100</span></b>);</span></span>
<span style="font-family: "times new roman";"><span style="white-space: normal;"> if (err) {</span></span>
<span style="font-family: "times new roman";"><span style="white-space: normal;"> dev_dbg(sdmmc_dev(host), "rtsx_usb_transfer_data error %d\n"</span></span>
<span style="font-family: "times new roman";"><span style="white-space: normal;"> , err);</span></span>
<div>
</div>
<div>
</div>
</pre>
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="about:invalid#zClosurez" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"></a></div>
<a href="about:invalid#zClosurez" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"></a><br />
<br />
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; margin: 0px; orphans: 2; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">
<br /></div>
Apparently, the SD card protocol is -so- tolerant for slow controller replies (because of the the whole wear-leveling load they must bare), that the driver must take these huge delays into account. (It -might- just still reply).<br />
<br />
As a result, this patch is not "correct" according to the SD card spec.<b> But in my case, it managed to increase the read speed of the card dramatically! </b><br />
<br />
I quickly patched the module, and rebuilt it for the current kernel. A simple module reload (without even a reboot) fixed the slowdown issue.<br />
<br />
After a few hours, I managed to let photorec parse the full 64GB of the card!<br />
<br />
<h2>
4. The end result</h2>
<br />
Thanks to photorec, and a small kernel driver patch I managed to recover about 30GB of pictures out of the 64GB on the card!<br />
<br />
Given the fact that the card did not show up anymore in windows at all (probably because of the same timeout issue), this is a pretty good result for a software-only recovery!<br />
<br />
As mentionned, doing a physical teardown of the card and reading the NAND directly might have recovered just a bit more. But for a non-invasive method, I don't think this is a bad result at all:)<br />
<br />
<br />
Thanks again for linux and the open source community:)<br />
<div>
<br /></div>
<br />
<br />
<br />arre234http://www.blogger.com/profile/04807961375666237936noreply@blogger.com1tag:blogger.com,1999:blog-1960944672511790691.post-15585347542497351892018-02-15T12:04:00.000-08:002018-03-03T06:51:01.801-08:00Linux portable wifi guitar amp on an orange pi zero<h2>
Introduction</h2>
<h3>
The problem</h3>
<div>
<div>
I have an electric guitar laying around as well as a cheap vox amp. The problem with this is:<br />
<br /></div>
<div>
-<span style="white-space: pre;"> </span>The amp I have now has limited effects</div>
<div>
-<span style="white-space: pre;"> </span>To avoid making too much noise during practicing I would like to use my wireless headset </div>
<div>
The vox amp I have obviously allows a jack out to a wired headset, but that gives me two cables to the amp!</div>
<div>
<br />
<br /></div>
</div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-jAqRu4dJVAg/WoXbdlFkzUI/AAAAAAAABjI/JI5lapJWp5kUMt76BaIXYFdqPWCbN6BlQCLcBGAs/s1600/cables.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="774" data-original-width="586" height="640" src="https://3.bp.blogspot.com/-jAqRu4dJVAg/WoXbdlFkzUI/AAAAAAAABjI/JI5lapJWp5kUMt76BaIXYFdqPWCbN6BlQCLcBGAs/s640/cables.png" width="483" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="MsoNormal">
I have been playing around with little linux devboards (like
the raspberry pi) for quite a while, and figured it must be possible to do
–some- sort of amp emulation onto it. So I head out for a little project.</div>
<div class="MsoNormal">
<br /></div>
<h3>
The solution</h3>
<div>
<div class="MsoNormal">
And behold, a wifi-connected linux arm box in my pants, serving
as portable amp + wireless transmitter</div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-p2TtrGTeuoY/WoXbxCLprmI/AAAAAAAABjM/sbY04zRUpXoJoCk9jKb94wt8T3AypbLuwCLcBGAs/s1600/pants.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="480" src="https://1.bp.blogspot.com/-p2TtrGTeuoY/WoXbxCLprmI/AAAAAAAABjM/sbY04zRUpXoJoCk9jKb94wt8T3AypbLuwCLcBGAs/s640/pants.png" width="640" /></a></div>
<div class="MsoNormal">
<br /></div>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-4hqHm5vcfWk/WoXb9kg7rrI/AAAAAAAABjQ/as9zk3kF7e0zeRbicWllvwS5c79x8qvHACLcBGAs/s1600/IMG_20180120_145207431_HDR.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="240" src="https://1.bp.blogspot.com/-4hqHm5vcfWk/WoXb9kg7rrI/AAAAAAAABjQ/as9zk3kF7e0zeRbicWllvwS5c79x8qvHACLcBGAs/s320/IMG_20180120_145207431_HDR.jpg" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="MsoNormal">
You can download the<a href="https://drive.google.com/file/d/1H8be9FOhea6YZ_ExDv6xd8meQfn182Ta/view?usp=sharing"> full SD card image for the hardware here.</a><br />
Just flash it, and use the same hardware as I did, and it will work! (password
root:guitar , wifipassword: guitarguitar)<br />
Surf though your favorite webbrowser
to <a href="http://172.24.1.1:8000/">http://172.24.1.1:8000</a> and control all
your virtual amp settings!</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
In case you are interested in all the details of the project, continue scrolling:)</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<h2>
The build and how-to</h2>
<div>
<br /></div>
<h3>
Step 1: Getting the basic hardware and software up and running</h3>
<div>
<br /></div>
<h4>
The guitar</h4>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-ekFvqKXm-ww/WoXc6VU8vvI/AAAAAAAABjc/DeRkNNL4vEk7NxzQlcjQL_pJdFK5LZUTQCLcBGAs/s1600/guitar.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="749" data-original-width="569" height="320" src="https://3.bp.blogspot.com/-ekFvqKXm-ww/WoXc6VU8vvI/AAAAAAAABjc/DeRkNNL4vEk7NxzQlcjQL_pJdFK5LZUTQCLcBGAs/s320/guitar.PNG" width="243" /></a></div>
<div>
<br /></div>
<div>
<div class="MsoNormal">
You obviously need an electric guitar. For the audio output, I have simple
converter to 3.5mm to connect to my linux box.</div>
<div class="MsoNormal">
<br /></div>
<h4>
The linux board</h4>
</div>
<div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
For the hardware I bumped into an article from cnx software
(<a href="https://www.cnx-software.com/2017/07/30/how-to-setup-an-orange-pi-zero-diy-smart-speaker-with-google-assistant-sdk/">https://www.cnx-software.com/2017/07/30/how-to-setup-an-orange-pi-zero-diy-smart-speaker-with-google-assistant-sdk/</a>)
showing a nice case for the orange pi zero along with an expansion board for
some more USB stuff. It is small, has a powerful processor, enough USB ports,
onboard wifi, and is very cheap (18$). Sure, a raspberry 3 would have done the
trick too for a bit more money, but I thought I’d give this one a try now. </div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
This is a small overview from <a href="http://www.orangepi.org/orangepizero/">http://www.orangepi.org/orangepizero/</a>
:</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-b592QYNa2h0/WoXdS8DpnpI/AAAAAAAABjk/w8ZGDYPvz5A9u_OEJcyFHt_OCH9YTt1pwCLcBGAs/s1600/orangepizero.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="373" data-original-width="656" height="226" src="https://4.bp.blogspot.com/-b592QYNa2h0/WoXdS8DpnpI/AAAAAAAABjk/w8ZGDYPvz5A9u_OEJcyFHt_OCH9YTt1pwCLcBGAs/s400/orangepizero.PNG" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="MsoNormal">
When shipped along with the expansionboard and case, it looks like this:</div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-vipNwwIw4aw/WoXdqx7M3JI/AAAAAAAABjw/QqvPAF89uoMzLMKvkE5-36cMTHJCUlbYgCLcBGAs/s1600/IMG_20180120_144314894.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="200" src="https://4.bp.blogspot.com/-vipNwwIw4aw/WoXdqx7M3JI/AAAAAAAABjw/QqvPAF89uoMzLMKvkE5-36cMTHJCUlbYgCLcBGAs/s200/IMG_20180120_144314894.jpg" width="150" /></a><a href="https://2.bp.blogspot.com/-Au_jUwjt7yo/WoXdf6nNoNI/AAAAAAAABjs/yGYZbYwqUxw75ETuBf7Wno0odfwLLwJqQCLcBGAs/s1600/IMG_20180120_144530535.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="200" src="https://2.bp.blogspot.com/-Au_jUwjt7yo/WoXdf6nNoNI/AAAAAAAABjs/yGYZbYwqUxw75ETuBf7Wno0odfwLLwJqQCLcBGAs/s200/IMG_20180120_144530535.jpg" width="150" /></a><a href="https://1.bp.blogspot.com/-sk6pT4Q0-5Y/WoXdfywomcI/AAAAAAAABjo/nyv6E5PLo8YqtVS9lQXQHaqvyCqxbyBYQCLcBGAs/s1600/IMG_20180120_144428396.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="200" src="https://1.bp.blogspot.com/-sk6pT4Q0-5Y/WoXdfywomcI/AAAAAAAABjo/nyv6E5PLo8YqtVS9lQXQHaqvyCqxbyBYQCLcBGAs/s200/IMG_20180120_144428396.jpg" width="150" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<h4>
An extra sound card</h4>
<div>
<br /></div>
<div>
<div class="MsoNormal">
Even though the expansion board has a jack out, it does not
offer jack-in. That’s sort of required to get the guitar sound inside of the
processor. 2$ (!) gets you this USB sound card which will do just fine :</div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-X00sdfBVNno/WoXeOMYaTjI/AAAAAAAABkA/k5l3SqZQA8U49vbEhShbXH7xnjOZAMVhQCLcBGAs/s1600/soundcartd.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="939" data-original-width="1600" height="187" src="https://1.bp.blogspot.com/-X00sdfBVNno/WoXeOMYaTjI/AAAAAAAABkA/k5l3SqZQA8U49vbEhShbXH7xnjOZAMVhQCLcBGAs/s320/soundcartd.png" width="320" /></a></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<h4>
My wireless headset</h4>
</div>
<div>
<br /></div>
<div>
<div class="MsoNormal">
This I had already (A Logitech H600), and use it mostly for
my laptop. I’m very happy with it. It interfaces towards linux as just another
USB sound card. Any other wireless headset will do, as long as it has linux
drivers for it.</div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-0-be59WuRhA/WoXeiVoZ_rI/AAAAAAAABkI/X1yX0hi5eeM-3XNlBD4kVU5EF9LoD29LACLcBGAs/s1600/headset.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1337" height="320" src="https://1.bp.blogspot.com/-0-be59WuRhA/WoXeiVoZ_rI/AAAAAAAABkI/X1yX0hi5eeM-3XNlBD4kVU5EF9LoD29LACLcBGAs/s320/headset.png" width="267" /></a></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<h4>
A power bank</h4>
</div>
<div>
<br /></div>
<div>
<div class="MsoNormal">
To avoid having to be connected to the grid for power, I
just use a 2A power bank, like this:</div>
<div class="MsoNormal">
<br /></div>
<br />
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
</div>
<a href="https://2.bp.blogspot.com/-BIzaifXz9ac/WoXe8P6sxpI/AAAAAAAABkU/CYyGPQcI2_4oG8K3rODtpMwefscsoAk0ACLcBGAs/s1600/bank.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-wzKs7E9BOEw/WoXexMD5kaI/AAAAAAAABkY/5QpkdYlz0UwHpKqMQPV-OgoL7OqZ3vqvwCEwYBhgL/s1600/IMG_20180120_144928636.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="320" src="https://1.bp.blogspot.com/-wzKs7E9BOEw/WoXexMD5kaI/AAAAAAAABkY/5QpkdYlz0UwHpKqMQPV-OgoL7OqZ3vqvwCEwYBhgL/s320/IMG_20180120_144928636.jpg" width="240" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-BIzaifXz9ac/WoXe8P6sxpI/AAAAAAAABk4/ONFATm-a4gU6EXN0RQFLQLbgIfeUpg87wCEwYBhgL/s1600/bank.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1217" data-original-width="1600" height="243" src="https://1.bp.blogspot.com/-BIzaifXz9ac/WoXe8P6sxpI/AAAAAAAABk4/ONFATm-a4gU6EXN0RQFLQLbgIfeUpg87wCEwYBhgL/s320/bank.png" width="320" /></a></div>
<h4>
</h4>
<div>
<br /></div>
<h4>
Everything together:</h4>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-4hqHm5vcfWk/WoXb9kg7rrI/AAAAAAAABjg/pLtS_ybC2R4eZsT2sOo28li_IDqIiVOZgCEwYBhgL/s1600/IMG_20180120_145207431_HDR.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="480" src="https://4.bp.blogspot.com/-4hqHm5vcfWk/WoXb9kg7rrI/AAAAAAAABjg/pLtS_ybC2R4eZsT2sOo28li_IDqIiVOZgCEwYBhgL/s640/IMG_20180120_145207431_HDR.jpg" width="640" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<h3>
Step 2: Running linux amp software</h3>
<div>
<br /></div>
<h4>
Jackd and guitarix</h4>
<div>
<br /></div>
<div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
I did not know this until I started this project, but as it
turns out some people already have been working hard at exactly what I was
searching for. The main project is called <b>guitarix</b>,
and it uses the low latency jackd as backend.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Please do check out their amazing work at guitarix.org</div>
<div class="MsoNormal">
They basically aim at running the software on a desktop pc,
and using their graphical interface:</div>
<div class="MsoNormal">
<br /></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-tHLDBS9FhRM/WoXfxZAluDI/AAAAAAAABkk/HpHQsjmQgl0foK5OaJz6XIr9nAqg2S1rgCLcBGAs/s1600/guit1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="339" data-original-width="496" height="218" src="https://4.bp.blogspot.com/-tHLDBS9FhRM/WoXfxZAluDI/AAAAAAAABkk/HpHQsjmQgl0foK5OaJz6XIr9nAqg2S1rgCLcBGAs/s320/guit1.png" width="320" /></a></div>
<div class="MsoNormal">
<br /></div>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-bLrRPom62MY/WoXfxK1VjeI/AAAAAAAABkg/SgsP_FN0vxkIfaabR_eZZoLIPcI5tgDTwCLcBGAs/s1600/gui2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="130" data-original-width="506" height="82" src="https://4.bp.blogspot.com/-bLrRPom62MY/WoXfxK1VjeI/AAAAAAAABkg/SgsP_FN0vxkIfaabR_eZZoLIPcI5tgDTwCLcBGAs/s320/gui2.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="MsoNormal">
Together with jackd (qjackctl screenshot above) you can
quite quickly turn a PC with a basic sound card (e.g microphone in and
headphones out) into a guitar amp with loads of effects!</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b>I would really recommend trying this out</b>. You just need to
download a liveCD. I used the one they recommend (AV linux) <a href="http://www.bandshed.net/AVLinux.html">http://www.bandshed.net/AVLinux.html</a>;
and tried it on my laptop. And it worked! </div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="MsoNormal">
I also got it to work with my headset, however I did need to
set a samplerate of 48000 (instead of 44100, since the audio driver from my
headset did not support that rate)</div>
<br />
<h4>
Running it on the orange pi</h4>
<div>
<br /></div>
<div>
<div class="MsoNormal">
So far so good, I had the setup running on a PC. Now I just
had to do the same thing on a smaller pc. Simple right?</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<u>Operating system</u></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Where raspberry pi’s have a debian based distro called
raspbian, these “other arm boards” also
have a distro backing them called “armbian”. It’s pretty cool, and worth
checking out at <a href="https://www.armbian.com/orange-pi-zero/">https://www.armbian.com/orange-pi-zero/</a>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
I just downloaded the “stable” version, flashed it on an SD
card, and ran it. It works. Just connected to Ethernet, let DHCP do its job,
and log in</div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #888888;">ogin as: root</span>
<span style="color: #888888;">root@172.24.1.1's password:</span>
<span style="color: #888888;"> ___ ____ _ _____</span>
<span style="color: #888888;"> / _ \ _ __ __ _ _ __ __ _ ___ | _ \(_) |__ /___ _ __ ___</span>
<span style="color: #888888;">| | | | '__/ _` | '_ \ / _` |/ _ \ | |_) | | / // _ \ '__/ _ \</span>
<span style="color: #888888;">| |_| | | | (_| | | | | (_| | __/ | __/| | / /| __/ | | (_) |</span>
<span style="color: #888888;"> \___/|_| \__,_|_| |_|\__, |\___| |_| |_| /____\___|_| \___/</span>
<span style="color: #888888;"> |___/</span>
<span style="color: #888888;">Welcome to ARMBIAN 5.35 user-built Ubuntu 16.04.3 LTS 4.14.8-rt9-sunxi</span>
<span style="color: #888888;">System load: 0.17 0.21 0.18 Up time: 11 min Local users: 2</span>
<span style="color: #888888;">Memory usage: 23 % of 493MB IP: 169.254.6.213 172.24.1.1</span>
<span style="color: #888888;">CPU temp: 56°C</span>
<span style="color: #888888;">Usage of /: 14% of 15G</span>
<span style="color: #888888;">Last login:</span>
</pre>
</div>
<div class="MsoNormal">
<br />
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
Armbian also comes with a handy tool called armbian-config,
which does the hard work for you to set up the wifi chip as APmode:</div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-wTgTzSF3JAw/WoXgO0-q4AI/AAAAAAAABko/hSyEopT5z3ckegFjeSf6voHG57mR3pqRgCLcBGAs/s1600/apmode.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="294" data-original-width="437" height="215" src="https://4.bp.blogspot.com/-wTgTzSF3JAw/WoXgO0-q4AI/AAAAAAAABko/hSyEopT5z3ckegFjeSf6voHG57mR3pqRgCLcBGAs/s320/apmode.png" width="320" /></a></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Once that’s done, we can continue with installing jackd and
guitarix </div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
</div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #888888;">apt-get install jackd qjackctl guitarix</span>
</pre>
</div>
<div class="MsoNormal" style="text-indent: .5in;">
<br /></div>
</div>
<u>Trying Jackd</u><br />
<br />
<div class="MsoNormal">
So, how do we run jackd? On the liveCD, I used qjackctl to
configure it. However, the orange pi zero has no HDMI output, so running
graphical applications is not trivial. </div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
I installed Xming (<a href="https://sourceforge.net/projects/xming/">https://sourceforge.net/projects/xming/</a>
). This very cool piece of software runs an X server on windows. (If you run
linux natively, you can of course skip this step, since you are most likely already
running an X server)</div>
<div class="MsoNormal">
<br /></div>
<br />
<div class="MsoNormal">
Once that’s done, you can just start an SSH session with
X-forwarding. If you run linux natively, this is just doing ssh –X
root@IPADDRESS. In my case, I set up putty on windows do to the trick.</div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-uFe3JoDcga8/WoXhaHyZ77I/AAAAAAAABk8/DMgmaV1Ed5cM5b8LmE5UP3-nt8ylSIuJwCLcBGAs/s1600/xming-passthrough.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="941" data-original-width="1255" height="478" src="https://4.bp.blogspot.com/-uFe3JoDcga8/WoXhaHyZ77I/AAAAAAAABk8/DMgmaV1Ed5cM5b8LmE5UP3-nt8ylSIuJwCLcBGAs/s640/xming-passthrough.PNG" width="640" /></a></div>
<br />
<div class="MsoNormal">
Once qjackctl ran, I tried to simply loop the audio from the
input (microphone) to my headset (stereo). By clicking connections, you can do
this. Note again that I had to match the samplerate to 48000 to make it work. </div>
<div class="MsoNormal">
<br /></div>
<br />
<div class="MsoNormal">
If I did change the frame size lower (to reduce latency) I
did run into quite a lot of issues of xruns and hang-ups of jackd, which I
addressed in the following steps. But at least now already the basic concept
worked!</div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-vtjRiqkw0kA/WoXhuNEtx4I/AAAAAAAABlE/Ck0YtEWfW2sgtEpyhRnMbWoLnPu6ePNEACLcBGAs/s1600/jackaudio.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="334" data-original-width="392" height="272" src="https://4.bp.blogspot.com/-vtjRiqkw0kA/WoXhuNEtx4I/AAAAAAAABlE/Ck0YtEWfW2sgtEpyhRnMbWoLnPu6ePNEACLcBGAs/s320/jackaudio.png" width="320" /></a></div>
<div class="MsoNormal">
<u>Trying guitarix</u></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
With jackd running, I tried running guitarix.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: "calibri" , "sans-serif"; font-size: 11.0pt; line-height: 115%;">Success!</span></div>
<div class="MsoNormal">
<span style="font-family: "calibri" , "sans-serif"; font-size: 11.0pt; line-height: 115%;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: "calibri" , "sans-serif"; font-size: 11.0pt; line-height: 115%;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-N9PRI85GXYA/WoXiAKMzb0I/AAAAAAAABlI/Jhr-6hQzylMZ31xsb1A6zR9Jx2-vPeaSwCLcBGAs/s1600/guitarix.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="639" data-original-width="550" height="320" src="https://4.bp.blogspot.com/-N9PRI85GXYA/WoXiAKMzb0I/AAAAAAAABlI/Jhr-6hQzylMZ31xsb1A6zR9Jx2-vPeaSwCLcBGAs/s320/guitarix.PNG" width="275" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="MsoNormal">
Even though there is still a huge delay, you can now use all
the effects of guitarix on the mini PC!!</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<h3>
Step 3: Running guitarix headless (without x server)</h3>
<div>
<br /></div>
<h4>
A headless read-only system</h4>
<div>
<br /></div>
<div>
<div class="MsoNormal">
Even though the proof of concept worked, I still needed
X-forwarding to run guitarix. The end goal is of course is to run the deamons
without any screen attached, just a boot. Moreover, one way or another, SD
cards will let you down eventually when you use them as a rw filesystem. But as
long as you use them read-only, it just works. And you can unplug the device at any point in time, without ever
having to worry about filesystem corruption.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Making jackd and guitarix run in a read-only headless
environment wasn’t exactly trivial. But some googling and hands-on testing got
me there.</div>
<div class="MsoNormal">
<br /></div>
</div>
<h4>
Headless jackd</h4>
<div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Since the jackd installed by the debian package was built
with dbus, it does not like starting without any X-related dbus stuff
apparently. But, there is a simple hack around this:</div>
<div class="MsoNormal">
<br /></div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #007020;">export </span><span style="color: #996633;">DBUS_SESSION_BUS_ADDRESS</span><span style="color: #333333;">=</span>unix:path<span style="color: #333333;">=</span>/run/dbus/system_bus_socket
/usr/bin/jackd -dalsa -r48000 -p256 -D -Chw:Device,0 -Phw:Headset,0 &
</pre>
</div>
<div class="MsoNormal">
<br />
Jackd did not have any issue not being able to write to the
filesystem, so read-only mode worked just fine.</div>
</div>
<div class="MsoNormal">
<br /></div>
<h4>
Headless guitarix</h4>
<div>
<br /></div>
<div>
<div class="MsoNormal">
Guitarix needs the bash home variable in order to try and
find the config. If I try to run a script from rc.local for example, this is
not set. Hence, the following is needed:</div>
<div class="MsoNormal">
<br /></div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #007020;">export </span><span style="color: #996633;">HOME</span><span style="color: #333333;">=</span>/root
</pre>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Guitarix also really does not like read-only filesystems. It
tries to write some config every time it starts, and if it fails, it gives up.
So basically what I quickly came up with, is to mount a tmpfs in the guitarix
directory, which is rw. The changes will be lost, but that’s fine by me. I
tarred the current config of guitarix which I found nice, and made sure it was
restored each boot.</div>
<div class="MsoNormal">
<br /></div>
</div>
<div>
<br /></div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">mount -t tmpfs none /root/.config/guitarix/
mount -t tmpfs none /var/lib/misc/
cp /root/guitarixconf.tar /root/.config/guitarix/
<span style="color: #007020;">cd</span> /root/.config/guitarix/
tar xf guitarixconf.tar
guitarix -i system:capture_1 -o system:playback_1 -o system:playback_2 -b E:1 -nogui &
</pre>
</div>
<br />
<br />
<h3>
Controlling guitarix through wifi</h3>
<div>
<br /></div>
<div>
<div class="MsoNormal">
I now had the system booting directly into a mode where the
linux amp kicked in, but what if I wanted to change a setting? Like the gain,
effects, etc.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Turns out guitarix has a JSON-API and a python webserver
with a basic <b>webinterface to do just
that</b>!</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Just start the python program after starting guitarix, and
navigate to the website. Ideal for surfing to on your smartphone to control the
device!</div>
<div class="MsoNormal">
<br /></div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #007020;">cd</span> /root/guitarix-webui/guitarix-webui-0.34.0/websockify/
python websocketproxy.py --web<span style="color: #333333;">=</span>../webui <span style="background-color: #fff0f0;">'*'</span>:8000 localhost:7000
</pre>
</div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-jUzU5uGnnLA/WoXircuEAyI/AAAAAAAABlY/Gh3Uu43z_EUBTQv5QCoExZBBQTPCZ1yiQCLcBGAs/s1600/guitarix-webapi2.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="699" data-original-width="617" height="320" src="https://2.bp.blogspot.com/-jUzU5uGnnLA/WoXircuEAyI/AAAAAAAABlY/Gh3Uu43z_EUBTQv5QCoExZBBQTPCZ1yiQCLcBGAs/s320/guitarix-webapi2.PNG" width="282" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-evgXw3tP_Jc/WoXirf1wY8I/AAAAAAAABlU/XGknJ9yrk4s464KseQwyBOpcKa_GCwozQCLcBGAs/s1600/guitarix-webapi.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="709" data-original-width="612" height="320" src="https://2.bp.blogspot.com/-evgXw3tP_Jc/WoXirf1wY8I/AAAAAAAABlU/XGknJ9yrk4s464KseQwyBOpcKa_GCwozQCLcBGAs/s320/guitarix-webapi.PNG" width="276" /></a></div>
<br />
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
To allow using a smartphone to connect wirelessly to the
box, you can configure a wireless hotspot on the zero. The armbian has a nice
tool (like rpi-config) that allows you to set this up. If you want to do it
manually, just configure hostapd and dnsmasq appropriately, and let linux take
care of the magic.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<h3>
Step 4: Reducing latency with a realtime kernel</h3>
<h3>
</h3>
<div class="MsoNormal">
I basically did step 2 and 3 in about one evening. Getting
the latency down took more than double of the time, but was also a pretty cool
investigation.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
As every line of the jackd or guitarix documentation says,
you should run this on a real-time kernel. The armbian image I downloaded did
not run this, hence the issues when trying to go to lower delays. So, up to
recompiling a new kernel!</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<h4>
RT-linux patching</h4>
</div>
<div>
<div class="MsoNormal">
In contrast to the raspberry pi, the linux kernel support
for the orange pi (sunxi) is rather shady. Especially if you want the video
acceleration, you basically are forced to stay at an old 3.x kernel, which is
again different from mainline</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
This is important, since in order to get real good real-time
performance, you should use 1) a recent kernel, and 2) apply the RT patch (<a href="https://rt.wiki.kernel.org/index.php/Main_Page">https://rt.wiki.kernel.org/index.php/Main_Page</a>)</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
There is a topic on armbian which covered this: <a href="https://forum.armbian.com/topic/1885-rt-patches-for-sun8i-kernel/">https://forum.armbian.com/topic/1885-rt-patches-for-sun8i-kernel/</a>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
People reported good results by trying a current mainline in
the armbian build tool and applying the RT-patch. So I set out to do the same.</div>
</div>
<div>
<br /></div>
<div>
<u>Building a new kernel</u></div>
<div>
<u><br /></u></div>
<div>
<div class="MsoNormal">
Turns out that building a kernel for armbian is pretty easy.
Just follow <a href="https://docs.armbian.com/Developer-Guide_Build-Preparation/">https://docs.armbian.com/Developer-Guide_Build-Preparation/</a>
</div>
<div class="MsoNormal">
<br /></div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">git clone --depth 1 https://github.com/armbian/build
<span style="color: #007020;">cd </span>build
./compile.sh
</pre>
</div>
<div class="MsoNormal">
You get a nice menu that allows you to select which kernel
to build, allows you to change kernel options etc. <br />
It does automatically apply a set of patches in the folder “userpatches”</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<u>Building a specific kernel with the RT patch</u></div>
<div class="MsoNormal">
<u><br /></u></div>
<div class="MsoNormal">
At the time of writing, the latest mainline kernel with an
RT patch was 4.18.8-RT9</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
I downloaded the patch, and placed it into the appropriate
directory:</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
ls userpatches/kernel/sunxi-next/<br />
patch-4.14.8-rt9.patch</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Then I did not immediately find a way to specify to the
build tool to fetch a specific tag of the linux kernel (instead of default to the very
latest) Doing a small patch was the fastest way I got it working. :</div>
<div class="MsoNormal">
<br /></div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: navy; font-weight: bold;">diff --git a/config/sources/sunxi_common.inc b/config/sources/sunxi_common.inc</span>
<span style="color: navy; font-weight: bold;">index 4fc872f..aae8829 100644</span>
<span style="color: #a00000;">--- a/config/sources/sunxi_common.inc</span>
<span style="color: #00a000;">+++ b/config/sources/sunxi_common.inc</span>
<span style="color: purple; font-weight: bold;">@@ -24,7 +24,8 @@ case $BRANCH in</span>
next)
KERNELSOURCE=$MAINLINE_KERNEL_SOURCE
<span style="color: #a00000;">- KERNELBRANCH='branch:linux-4.14.y'</span>
<span style="color: #00a000;">+ #KERNELBRANCH='branch:linux-4.14.y'</span>
<span style="color: #00a000;">+ KERNELBRANCH='tag:v4.14.8'</span>
KERNELDIR=$MAINLINE_KERNEL_DIR
GOVERNOR=ondemand
</pre>
</div>
<div class="MsoNoSpacing">
<br /></div>
<div class="MsoNoSpacing">
(Note that I used the following tag of the armbian build
repo: 9531d1bc7ecd0f468e29e402ba00cbc7b7dd683f)</div>
<div class="MsoNoSpacing">
<br /></div>
<div class="MsoNoSpacing">
After running another compile.sh, and enabling the
correct options in the linux kernel menu (PREEMPT_RT_FULL), this gives a new
uboot and new kernel debian packages.</div>
<div class="MsoNoSpacing">
<br /></div>
<div class="MsoNormal">
</div>
<div class="MsoNoSpacing">
These can just be uploaded and installed on the target. A
new reboot and you are running a very fresh, very fast recent linux kernel!</div>
<div class="MsoNormal">
<u><br /></u></div>
<div class="MsoNormal">
<u><br /></u></div>
<h4>
Fixing fixed frequency for effective RT behavior</h4>
</div>
<div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
A good program to test the RT behavior is cyclic test. The
output looks somewhat like this:</div>
<div class="MsoNormal">
<br /></div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #888888;">Linux orangepizero 4.14.8-rt9-sunxi #1 SMP PREEMPT RT Sat Jan 6 14:36:31 CET 2018 armv7l armv7l armv7l GNU/Linux</span>
<span style="color: #888888;">/root/rt-tests/cyclictest -p 80 -t5 –n</span>
<span style="color: #c65d09; font-weight: bold;">#</span> /dev/cpu_dma_latency <span style="color: #007020;">set </span>to 0us
<span style="color: #888888;">policy: fifo: loadavg: 0.85 0.49 0.22 4/168 3083</span>
<span style="color: #888888;">T: 0 ( 3079) P:80 I:1000 C: 3297 Min: 8 Act: 17 Avg: 16 Max: 66</span>
<span style="color: #888888;">T: 1 ( 3080) P:80 I:1500 C: 2198 Min: 8 Act: 24 Avg: 15 Max: 50</span>
<span style="color: #888888;">T: 2 ( 3081) P:80 I:2000 C: 1648 Min: 8 Act: 11 Avg: 16 Max: 60</span>
<span style="color: #888888;">T: 3 ( 3082) P:80 I:2500 C: 1318 Min: 8 Act: 12 Avg: 15 Max: 44</span>
<span style="color: #888888;">T: 4 ( 3083) P:80 I:3000 C: 1098 Min: 9 Act: 17 Avg: 18 Max: 57</span>
</pre>
</div>
<div class="MsoNormal">
<br />
You should make sure the maximum latency stays below 100 at
least</div>
<div class="MsoNormal">
. </div>
<div class="MsoNormal">
In my first attempts with my newly compiled kernel, <b>this hit 3000+ regularly</b>! Meaning the
RT patch clearly was not effective. Turned out a bit more work was needed</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<u>CPU Frequency Scaling Govenor</u></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Apparently, to save power and dynamically adjust cpu
frequency, the linux cpu governor regularly changed frequency, and this had a
very bad effect on the RT behavior. When forcing the governor to performance
mode or userspace mode, I suddenly got much better results!</div>
<div class="MsoNormal">
<br /></div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #888888;">echo userspace > /sys/devices/system/cpu/cpufreq/policy0/scaling_governor</span>
<span style="color: #888888;">echo 960000 > /sys/devices/system/cpu/cpufreq/policy0/scaling_min_freq</span>
<span style="color: #888888;">echo 960000 > /sys/devices/system/cpu/cpufreq/policy0/scaling_setspeed</span>
</pre>
</div>
<div class="MsoNormal">
<u><br /></u>
<u>Forcing fixed frequency</u></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
You’d think that that was the end of it, and so did I.
Strangely enough, even when forcing the governor to a fixed frequency, the
linux kernel –still- once in a while (like after a minute, depending on jackd
realtime settings) shifted frequency, causing massive spikes in latency, and
freaking out jackd. After investigating the kernel a bit further, it seems that
it has some sort of protection that it will force to a lower operating point (OPP)
regardless of the governor, to avoid any damage to the CPU whatsoever. Even
though that sounds like a nice feature, the CPU can handle this load just fine,
and this just messes up the real-time behavior.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
The final fix that I needed to do to get consistently good
RT performance, was to remove all other operation points from the device tree!
You can simply decompile the devicetree and recompile it using the DTC tool
like so:</div>
<div class="MsoNormal">
<br /></div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #888888;">dtc -I dtb -O dts sun8i-h2-plus-orangepi-zero.dtb > sun8i-h2-plus-orangepi-zero.dts</span>
<span style="color: #888888;">dtc -I dts -O dtb sun8i-h2-plus-orangepi-zero.dts > sun8i-h2-plus-orangepi-zero.dtb</span>
</pre>
</div>
<div class="MsoNormal">
<br />
Once in the dts format, you just locate the operating
points, and only leave in the 960Mhz.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
And success! Cyclic test keeps running forever without any
spikes!</div>
<div class="MsoNormal">
<br /></div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">root@orangepizero:~#</span> uname -a
<span style="color: #888888;">Linux orangepizero 4.14.8-rt9-sunxi #1 SMP PREEMPT RT Sat Jan 6 14:36:31 CET 2018 armv7l armv7l armv7l GNU/Linux</span>
<span style="color: #888888;">/root/rt-tests/cyclictest -p 80 -t5 –n</span>
<span style="color: #c65d09; font-weight: bold;">#</span> /dev/cpu_dma_latency <span style="color: #007020;">set </span>to 0us
<span style="color: #888888;">policy: fifo: loadavg: 0.85 0.49 0.22 4/168 3083</span>
<span style="color: #888888;">T: 0 ( 3079) P:80 I:1000 C: 3297 Min: 8 Act: 17 Avg: 16 Max: 66</span>
<span style="color: #888888;">T: 1 ( 3080) P:80 I:1500 C: 2198 Min: 8 Act: 24 Avg: 15 Max: 50</span>
<span style="color: #888888;">T: 2 ( 3081) P:80 I:2000 C: 1648 Min: 8 Act: 11 Avg: 16 Max: 60</span>
<span style="color: #888888;">T: 3 ( 3082) P:80 I:2500 C: 1318 Min: 8 Act: 12 Avg: 15 Max: 44</span>
<span style="color: #888888;">T: 4 ( 3083) P:80 I:3000 C: 1098 Min: 9 Act: 17 Avg: 18 Max: 57</span>
</pre>
</div>
<div class="MsoNoSpacing">
<u><br /></u>
<u>Important sidenote of fixed OPP</u></div>
<div class="MsoNoSpacing">
<u><br /></u></div>
<div class="MsoNormal">
One important sidenote of using a fixed opp, is that in very
heavy load, the cpu actually becomes so warm that the linux kernel (having no
other option since we removed the other OPPs) decides to reboot the device! I
only saw this ever happening when running a parallel compilation on all 4 cores
though. When just using it with guitarix/webstuff, I never got it to crash so
far:) You can also just lower the frequency or go save with a heatsink of
course if you’d want to.</div>
<div class="MsoNormal">
<br /></div>
<h3>
Patching jackd to deal with latency spikes</h3>
</div>
<div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
While investigating the RT issues with the linux kernel, I
also noticed that jackd really got completely messed up when it received a bit
latency spike. Instead of noting an XRUN and just recovering, it never did
recover. I always then had to kill the process with the SIGKILL, and restart
it. Even though that works, it is really slow and requires manual action.
Surely there must be a better way?</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
And there is. Turns out there was a bug in the jackd alsa
driver when coping with xruns</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
In the function alsa_driver_xrun_recovery, the linux driver
is not told to again reset its buffers to a sane position upon overrun. As a
result, after a recovery, immediately another overrun can occur. To fix this, I
just had to trigger a recovery (snd_pcm_prepare) after an actual xrun was
detected:<br />
<br /></div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">if</span> (snd_pcm_status_get_state(status) <span style="color: #333333;">==</span> SND_PCM_STATE_XRUN <span style="color: #333333;">&&</span> driver<span style="color: #333333;">-></span>process_count <span style="color: #333333;">></span> XRUN_REPORT_DELAY) {
<span style="color: #008800; font-weight: bold;">struct</span> timeval now, diff, tstamp;
driver<span style="color: #333333;">-></span>xrun_count<span style="color: #333333;">++</span>;
snd_pcm_status_get_tstamp(status,<span style="color: #333333;">&</span>now);
snd_pcm_status_get_trigger_tstamp(status, <span style="color: #333333;">&</span>tstamp);
timersub(<span style="color: #333333;">&</span>now, <span style="color: #333333;">&</span>tstamp, <span style="color: #333333;">&</span>diff);
<span style="color: #333333;">*</span>delayed_usecs <span style="color: #333333;">=</span> diff.tv_sec <span style="color: #333333;">*</span> <span style="color: #6600ee; font-weight: bold;">1000000.0</span> <span style="color: #333333;">+</span> diff.tv_usec;
jack_log(<span style="background-color: #fff0f0;">"**** alsa_pcm: xrun of at least %.3f msecs"</span>,<span style="color: #333333;">*</span>delayed_usecs <span style="color: #333333;">/</span> <span style="color: #6600ee; font-weight: bold;">1000.0</span>);
<span style="color: red;"><span style="font-weight: bold;">if</span> (driver<span style="color: #333333;">-></span>capture_handle) {
<span style="font-weight: bold;">if</span> ((res <span style="color: #333333;">=</span> snd_pcm_prepare(driver<span style="color: #333333;">-></span>capture_handle)) <span style="color: #333333;"><</span> <span style="font-weight: bold;">0</span>) {
jack_error(<span style="background-color: #fff0f0;">"error preparing after xrun: %s"</span>, snd_strerror(res));
}
} <span style="font-weight: bold;">else</span> {
<span style="font-weight: bold;">if</span> ((res <span style="color: #333333;">=</span> snd_pcm_prepare(driver<span style="color: #333333;">-></span>playback_handle)) <span style="color: #333333;"><</span> <span style="font-weight: bold;">0</span>) {
jack_error(<span style="background-color: #fff0f0;">"error preparing after xrun: %s"</span>, snd_strerror(res));
}</span>
</pre>
</div>
<div class="MsoNoSpacing" style="margin-left: .5in;">
<br /></div>
<div class="MsoNoSpacing">
<br /></div>
<div class="MsoNormal">
I downloaded the source using apt-get source, and built it
again with debuild –us –uc, and installed it locally. And voila, a working
system!</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<h2>
Conclusion</h2>
</div>
<div>
<br /></div>
<div>
This was a cool project, which hadn't been possible for the awesome open source community that provided many of the tools and toys to make this possible. </div>
<div>
<br /></div>
<div>
Linux rocks:)</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-32X0OlwL0K4/WoXmbmIATDI/AAAAAAAABls/d0FJ6hSTb-8VnfhjnSYpmPWjI45XyfnJgCLcBGAs/s1600/linux.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="256" data-original-width="256" height="200" src="https://2.bp.blogspot.com/-32X0OlwL0K4/WoXmbmIATDI/AAAAAAAABls/d0FJ6hSTb-8VnfhjnSYpmPWjI45XyfnJgCLcBGAs/s200/linux.jpg" width="200" /></a></div>
<a href="https://3.bp.blogspot.com/-p7c0RW9BYkI/WoXmbej5eDI/AAAAAAAABlo/nIKj1NN6o2EEv-CyfSntpKr-lMwVxqn-QCLcBGAs/s1600/rock_tux.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="256" data-original-width="256" height="200" src="https://3.bp.blogspot.com/-p7c0RW9BYkI/WoXmbej5eDI/AAAAAAAABlo/nIKj1NN6o2EEv-CyfSntpKr-lMwVxqn-QCLcBGAs/s200/rock_tux.png" width="200" /></a><br />
<div>
<br /></div>
<div>
<span style="font-family: "calibri" , "sans-serif"; font-size: 11.0pt; line-height: 115%;"><!--[if gte vml 1]><v:shapetype id="_x0000_t75" coordsize="21600,21600"
o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f"
stroked="f">
<v:stroke joinstyle="miter"/>
<v:formulas>
<v:f eqn="if lineDrawn pixelLineWidth 0"/>
<v:f eqn="sum @0 1 0"/>
<v:f eqn="sum 0 0 @1"/>
<v:f eqn="prod @2 1 2"/>
<v:f eqn="prod @3 21600 pixelWidth"/>
<v:f eqn="prod @3 21600 pixelHeight"/>
<v:f eqn="sum @0 0 1"/>
<v:f eqn="prod @6 1 2"/>
<v:f eqn="prod @7 21600 pixelWidth"/>
<v:f eqn="sum @8 21600 0"/>
<v:f eqn="prod @7 21600 pixelHeight"/>
<v:f eqn="sum @10 21600 0"/>
</v:formulas>
<v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/>
<o:lock v:ext="edit" aspectratio="t"/>
</v:shapetype><v:shape id="_x0000_i1025" type="#_x0000_t75" style='width:439.5pt;
height:580.5pt'>
<v:imagedata src="file:///C:\Users\Arnout\AppData\Local\Temp\msohtmlclip1\01\clip_image001.png"
o:title="cables"/>
</v:shape><![endif]--><!--[if !vml]--><!--[endif]--></span></div>
arre234http://www.blogger.com/profile/04807961375666237936noreply@blogger.com50tag:blogger.com,1999:blog-1960944672511790691.post-16759699342008580142013-08-22T12:01:00.000-07:002018-02-10T00:51:26.561-08:00My Electric Scooter Project<br />
<div style="text-align: center;">
<span style="font-size: x-large;"><u>The concept</u></span></div>
<br />
The concept of my project, was to upgrade my (2 kW 48V) electric scooter (a<a href="http://www.qwic.be/nl-NL/elektrische-scooters/15-emoto-87.html"> Qwic Emoto 87</a>), with an LCD display, showing the voltage of the batterypack, the current flowing through it, the current power usage etc.<br />
<br />
From an electronics point of view, this is quite easy; Hook up the voltages to a resistor divider, measure the current via a shunt or something, and process this info using a microcontroller, which also controls the LCD.<br />
<br />
The final result speaks for itself in the video's below:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dyx-U7rD00PKrBhJ16R8tl9W46cisQuc1uX22liGa1oUlRw8QUC1JxvxZS6v25wGZdwMCYU1Mr6cxq2mJYyOg' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div>
<div class="" style="clear: both; text-align: center;">
(The finished project)<br />
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dzE1pp22SjjFJzZZVUXpzLj5EULZDhuJtRITcbELBhWz5XhY8LS9WVEfyd93V4wX3UMmYdtq4iE1C45y71ICQ' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div>
<div class="separator" style="clear: both; text-align: center;">
(The nutty testdrives)</div>
<br />
<br />
In the next sections, I'll try to go over what I did exactly to get to this point. I'll explain what stuff I bought, how I put it together, how the software is designed etc. Hopefully I can inspire other folks with this info, and give something back to the online community, that has helped me get this far.<br />
<br />
<div style="text-align: center;">
<span style="font-size: x-large;"><u>The Hardware</u></span></div>
<div style="text-align: center;">
<span style="font-size: x-large;"><u><br /></u></span></div>
<div style="text-align: center;">
<span style="font-size: x-large;"><u><br /></u></span></div>
<br />
<a href="http://3.bp.blogspot.com/-IlmXL_Z41PE/UhI_i92YrhI/AAAAAAAAA3E/ferCBqTqDV0/s1600/Foto-0331.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="150" src="https://3.bp.blogspot.com/-IlmXL_Z41PE/UhI_i92YrhI/AAAAAAAAA3E/ferCBqTqDV0/s200/Foto-0331.jpg" width="200" /></a><span style="font-size: large;">1. The Scooter</span><br />
<br />
(I already had this part:). I own a<a href="http://www.qwic.be/nl-NL/elektrische-scooters/15-emoto-87.html"> Qwic Emoto 87</a> since 2011, and most likely lost the warranty already anyway:) Since everything about it is electric, hooking some nice electronics to it is not too hard!<br />
<br />
<span style="font-size: large;">2. The Microcontroller</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.ti.com/diagrams/med_ek-lm4f120xl_stellarislaunchpad_tool.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://www.ti.com/diagrams/med_ek-lm4f120xl_stellarislaunchpad_tool.JPG" height="128" width="200" /></a></div>
<br />
The microcontroller was by far the most fun of the project for me:) I never actually played a lot with Arduino's or anything before, so you can imagine the world that opened when I ordered by TI Stellaris Launchpad Evaluation board (<a href="https://estore.ti.com/Stellaris-LaunchPad.aspx">for the amazing price of less than 10 euro's, including shipping</a>!)<br />
<br />
The board provides lots of GPIO pins that can be used for ADC measurements (for voltage & current in my case), and digital out (for the LCD).<br />
<br />
There's quite some material online to get started (although not much compared to the arduino projects:). It's typically programmed in C, although there is even a project called <a href="http://energia.nu/">Energia</a> that allows you to use arduino-like code. But if you are a bit experienced in C, TI have an awesome free, open, very well documented library called stellarisware, that'll definitely speed up any development!<br />
For more info on how I wrote the software etc, see the software section below<br />
<br />
<span style="font-size: large;">3. The LCD</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<a href="https://1.bp.blogspot.com/-mox06-2kosQ/Wn6yPI4loVI/AAAAAAAABiw/YC0-IBB-omAtFk6Umw9X-dTRpEX8wP9bwCLcBGAs/s1600/lcd.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="110" data-original-width="204" src="https://1.bp.blogspot.com/-mox06-2kosQ/Wn6yPI4loVI/AAAAAAAABiw/YC0-IBB-omAtFk6Umw9X-dTRpEX8wP9bwCLcBGAs/s1600/lcd.png" /></a>For the LCD that would eventually go onto the dashboard, I first scowered the web to see if anybody had already connected an LCD to the launchpad before. Turns out the HD44780 had been connected before by "The_YongGrand",<a href="http://forum.stellarisiti.com/topic/275-very-basic-hd44780-driver-for-stellaris-launchpad/"> and he published the library online</a>. Then I just ordered one off ebay for some 7 euro's.<br />
<br />
<span style="font-size: large;">4. The current measurement tool</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://i.ebayimg.com/00/s/MTE5NVgxNjAw/z/yMgAAOxyrUZRzPUO/$T2eC16h,!zoE9s5ngyKQBRzPUN604!~~60_57.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://i.ebayimg.com/00/s/MTE5NVgxNjAw/z/yMgAAOxyrUZRzPUO/$T2eC16h,!zoE9s5ngyKQBRzPUN604!~~60_57.JPG" height="149" width="200" /></a></div>
You might think a simple shunt would cut it. It would, but keep in mind that the scooter actually can draw some 40 amps at peak power, so choosing the shunt is not so trivial. You can try to find a one with a really small resistance value to avoid losing energy in it, but that pushes up the cost a bit. Thanks to a hint of somebody, I found these babies (see picture). They're precalibrated hall sensors, with the current flowing right through the chip on the lead-frame. In my case, I chose an "ACS756" chip, and ordered it off ebay again, for 6 euros<br />
<br />
<br />
<span style="font-size: large;">5. DC-DC converter</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-sX4oeGIQXyw/Wn6ycXlSfYI/AAAAAAAABi0/na6A6pkhL70L14g30Rb5RVQI4zbKNI5WQCLcBGAs/s1600/dcdc.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="137" data-original-width="204" src="https://4.bp.blogspot.com/-sX4oeGIQXyw/Wn6ycXlSfYI/AAAAAAAABi0/na6A6pkhL70L14g30Rb5RVQI4zbKNI5WQCLcBGAs/s1600/dcdc.png" /></a></div>
The LCD and microcontroller don't like 12V that much (let alone 48). A resistor divider can do the trick too, but is not very efficient and does not provide a stable output current*. A DC-DC converter efficiently gives you a stable output. You can build one yourself using the LM , coil & caps, but I chose to be lazy, and ordered one off ebay again for 10 euros:) It takes in up to 30V.<br />
<br />
<br />
* <span style="font-size: x-small;">In retrospect, a voltage divider -might- have worked too: The backlight of the LCD is not very intolerant of fluctuations, and the microcontroller has a voltage stabilizer on board. In addition, the whole system only draws 0.3W. The battery pack is supposed to be a giant cap so voltage peaks shouldn't be too much of a problem. So if you want to save a few euro's, but risk resetting the microcontroller if the pack is going empty, you might as well try the resistor divider.</span><br />
<br />
<span style="font-size: large;">6. Electronics kit</span><br />
<br />
If you're into electronics a bit, you'll probably have this stuff. But just to go over the shortlist of the things I used (that I can come up with):<br />
<br />
- Breadboard<br />
- Breadboard cables<br />
- Pinheaders<br />
- Soldering iron<br />
- Multimeter<br />
- Heat-shrink tubing<br />
- A perfboard / stripboard (a prototype PCB)<br />
- Gluegun (very useful, < 10euro's) :)<br />
...<br />
<br />
You can get most of this stuff quite cheap online/in your local hardware store<br />
<br />
<span style="font-size: large;">7. Mechanics kit</span><br />
<br />
If you're opening the scooter, you'll need some screwdrivers and wrenches..<br />
<br />
<br />
<br />
<div style="text-align: center;">
<span style="font-size: x-large;"><u>The software</u></span></div>
<span style="font-size: large;"><br /></span>
On the TI website you can find sort of all the things you need, although other websites have better tutorials about how to get started in my opinion:) TI does have the 8 video's or so of the entire system, but I never bothered to see them because they took too long:)<br />
<br />
<span style="font-size: x-small;">(I did actually watch (/scrolled through) these video's: </span><br />
<a href="http://www.youtube.com/playlist?list=PLPW8O6W-1chwyTzI3BHwBLbGQoPFxPAPM"><span style="font-size: x-small;">http://www.youtube.com/playlist?list=PLPW8O6W-1chwyTzI3BHwBLbGQoPFxPAPM</span></a><br />
<span style="font-size: x-small;">They're a very basic course for embedded programming, but they also show how to program the launchpad.)</span><br />
<br />
Anyway, to get started, you'll first need an IDE.<br />
<br />
<span style="font-size: large;">The IDE: Code Composer Studio</span><br />
<span style="font-size: large;"><br /></span>
I tried two IDE's, the IAR embedded workbench, and Code Composer Studio. The last one is developed by TI itself, and is a fork of Eclipse. I started with IAR, but landed at CCS:) I'm only going to cover using CCS here. (You can download it for free from TI's website, if you keep your code size limited)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-VFrgngke0p8/UhZX1RKoK4I/AAAAAAAABZQ/nAdcKj--JOo/s1600/CCS.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://3.bp.blogspot.com/-VFrgngke0p8/UhZX1RKoK4I/AAAAAAAABZQ/nAdcKj--JOo/s320/CCS.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
(What Code Composer Studio looks like on my PC)</div>
<br />
<span style="font-size: large;">The Stellarisware drivers</span><br />
<br />
To use the awesome library that is stellarisware, you'll first have to download & compile it. Later, you'll need to "link" the built library with all your projects, so that you can call code from it. I won't go into details, but just give a few pointers, regarding the project settings:<br />
<br />
1) Make sure you include stellarisware, and any other libs you refer to<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-0mrl1myoKEc/UhZaHfw8J3I/AAAAAAAABZk/3uFI8FzGJ3A/s1600/includes.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="181" src="https://1.bp.blogspot.com/-0mrl1myoKEc/UhZaHfw8J3I/AAAAAAAABZk/3uFI8FzGJ3A/s320/includes.png" width="320" /></a></div>
<br />
<br />
2) Predefined symbols: To correctly use/compile stellarisware, you'll have to specify your type of board<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-Zec2OGNmx_o/UhZaHMo9f3I/AAAAAAAABZo/IOPi1FunSfI/s1600/symbl.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="214" src="https://3.bp.blogspot.com/-Zec2OGNmx_o/UhZaHMo9f3I/AAAAAAAABZo/IOPi1FunSfI/s320/symbl.png" width="320" /></a></div>
<br />
3) Linker search path:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-3R7a5DNEpxg/UhZaFf5wiWI/AAAAAAAABZc/ExNaGt0BfVc/s1600/filesearchlinker.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="216" src="https://3.bp.blogspot.com/-3R7a5DNEpxg/UhZaFf5wiWI/AAAAAAAABZc/ExNaGt0BfVc/s320/filesearchlinker.png" width="320" /></a></div>
<br />
<br />
<br />
<br />
<span style="font-size: large;">The LCD Library</span><br />
<br />
Turns out the HD44780 had been connected before by "The_YongGrand",<a href="http://forum.stellarisiti.com/topic/275-very-basic-hd44780-driver-for-stellaris-launchpad/"> and he published the library online</a>. The lib & example are quite straightforward.<br />
<br />
Also the adafruit site is very very helpful: <a href="http://learn.adafruit.com/drive-a-16x2-lcd-directly-with-a-raspberry-pi/wiring">http://learn.adafruit.com/drive-a-16x2-lcd-directly-with-a-raspberry-pi/wiring</a><br />
<br />
Note that to get stuff from integers to strings, you'll need stuff from the C standard library. For simple microcontrollers, this is a bit overkill. However, TI has usnprintf functions in the stellarisware library that do the job just fine.<br />
<br />
<span style="font-size: large;">Using the temperature sensor with the ADC</span><br />
<span style="font-size: large;"><br /></span>
Something quite irrelevant for this project, but wanted to refer to this guy anyway:)<br />
<br />
Nemetila posted his/her code on ti's fora: <a href="http://forum.stellarisiti.com/topic/471-using-stellaris-launchpad-as-a-thermometer/">http://forum.stellarisiti.com/topic/471-using-stellaris-launchpad-as-a-thermometer/</a><br />
It shows how to do an ADC measurement, but also has a nice userspace application attached to the post! If you have the stellaris launchpad, this is definitely worth a go!<br />
<br />
<span style="font-size: large;">The Final Code</span><br />
<br />
You can find the whole code on github:<br />
<br />
<div style="text-align: center;">
<a href="https://github.com/arre525/escooterlcd"><b>https://github.com/arre525/escooterlcd</b></a></div>
<br />
<br />
<br />
<br />
<div style="text-align: center;">
<span style="font-size: x-large;"><u>The Assembly</u></span></div>
<br />
Getting the whole system working on my desk was one thing. But getting it actually installed in the scooter proved to be a challenge on its own:) I spent more time on it that I anticipated, mainly because I underestimated the time it takes to open a scooter, solder 50 cables and a PCB, and getting everything back together nicely:)<br />
<br />
<span style="font-size: large;">The Breadboard Prototype</span><br />
<span style="font-size: large;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-s8mNp1AK9cs/UhZMJyTKyZI/AAAAAAAABSY/08QLO7_QyTk/s1600/Foto-1326.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="240" src="https://2.bp.blogspot.com/-s8mNp1AK9cs/UhZMJyTKyZI/AAAAAAAABSY/08QLO7_QyTk/s320/Foto-1326.jpg" width="320" /></a></div>
In practice, you don't write the entire software the first time, and then start prototyping. To the right, you can see a pic of me getting the LCD to work for the first time, using the library as explained above.<br />
<br />
I can tell you, finally getting them letters on that screen is a good feeling:)<br />
<br />
<a href="http://2.bp.blogspot.com/-DpcHknmk3qo/UhZMxC1lMpI/AAAAAAAABSg/sHI_l1K_IRg/s1600/Foto-1335.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="150" src="https://2.bp.blogspot.com/-DpcHknmk3qo/UhZMxC1lMpI/AAAAAAAABSg/sHI_l1K_IRg/s200/Foto-1335.jpg" width="200" /></a><br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Once I got the LCD working, doing the voltage ADC measurements is quite trivial too. Testing the current sensor was more difficult, as I didn't have any current source of several amps.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-m0O9BdGffkE/UhZNWEsGQeI/AAAAAAAABSo/jojFpPtY6lk/s1600/Foto-1339.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="240" src="https://3.bp.blogspot.com/-m0O9BdGffkE/UhZNWEsGQeI/AAAAAAAABSo/jojFpPtY6lk/s320/Foto-1339.jpg" width="320" /></a></div>
<br />
<br />
<br />
I eventually just used the scooter's battery charger, and hooked up the sensor in series, together with a multimeter for calibration. Not extremely professional, but that did the trick.<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<span style="font-size: large;">The Scooter Battery Connections</span><br />
<span style="font-size: large;"><br /></span>
1. Opening the Scooter<br />
<span style="font-size: large;"><br /></span>
Just hooking up a few cables to the batteries might not seem a big a deal. It did however take me a whole afternoon to get it done:)<br />
<br />
Here's what the scooter looks like when you open it:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-juGp3hh7ROY/UhTuAeSeQJI/AAAAAAAAA5E/bgs03-vOg3E/s1600/Foto-1357.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"></a><a href="http://2.bp.blogspot.com/-2pgKUVfujRY/UhTuBEbF1iI/AAAAAAAAA5c/FzYBwG43TRU/s1600/Foto-1360.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="150" src="https://2.bp.blogspot.com/-2pgKUVfujRY/UhTuBEbF1iI/AAAAAAAAA5c/FzYBwG43TRU/s200/Foto-1360.jpg" width="200" /></a><img border="0" height="150" src="https://4.bp.blogspot.com/-juGp3hh7ROY/UhTuAeSeQJI/AAAAAAAAA5E/bgs03-vOg3E/s200/Foto-1357.jpg" style="cursor: move;" width="200" /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-hmkiWc59DKI/UhTuELeaI2I/AAAAAAAAA6g/9tQFdcYOemU/s1600/Foto-1369.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="150" src="https://1.bp.blogspot.com/-hmkiWc59DKI/UhTuELeaI2I/AAAAAAAAA6g/9tQFdcYOemU/s200/Foto-1369.jpg" width="200" /></a></div>
The thing on the top-right pic is the 40A controller. As you can see, after 2 years of service, the scooter get preeeetty dusty inside! <br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
2. Soldering the Hall Sensor<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-GOA4SW5v6UU/UhTuFSJ_P2I/AAAAAAAAA64/eqeQ9BxfNM0/s1600/Foto-1372.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="150" src="https://1.bp.blogspot.com/-GOA4SW5v6UU/UhTuFSJ_P2I/AAAAAAAAA64/eqeQ9BxfNM0/s200/Foto-1372.jpg" width="200" /></a><a href="http://4.bp.blogspot.com/-9jEnFWnbiVY/UhTuF-C468I/AAAAAAAAA7I/gIu22xlbCMg/s1600/Foto-1373.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="150" src="https://4.bp.blogspot.com/-9jEnFWnbiVY/UhTuF-C468I/AAAAAAAAA7I/gIu22xlbCMg/s200/Foto-1373.jpg" width="200" /></a></div>
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-WrbmzkXBp1k/UhTuF1niGfI/AAAAAAAAA7Q/PT-nmOo8Ql4/s1600/Foto-1374.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="150" src="https://3.bp.blogspot.com/-WrbmzkXBp1k/UhTuF1niGfI/AAAAAAAAA7Q/PT-nmOo8Ql4/s200/Foto-1374.jpg" width="200" /></a></div>
<a href="http://2.bp.blogspot.com/-X2sbzbYL540/UhTuGLTNbdI/AAAAAAAAA7M/VPdcoX2VB2M/s1600/Foto-1375.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="150" src="https://2.bp.blogspot.com/-X2sbzbYL540/UhTuGLTNbdI/AAAAAAAAA7M/VPdcoX2VB2M/s200/Foto-1375.jpg" width="200" /></a><br />
<div style="text-align: center;">
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: center;">
And here you've got some pics on the hall-sensor,</div>
</div>
<div style="text-align: center;">
<div style="text-align: center;">
with the battery connections soldered onto them. (The cables are actually way to thick, oh well:)</div>
</div>
<br />
<br />
<br />
<br />
<br />
<br />
3. Connecting some cables to the batteries<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-G4902wsc5Wg/UhTuHFp_sGI/AAAAAAAAA7k/PsRDkgf3Ark/s1600/Foto-1377.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="150" src="https://4.bp.blogspot.com/-G4902wsc5Wg/UhTuHFp_sGI/AAAAAAAAA7k/PsRDkgf3Ark/s200/Foto-1377.jpg" width="200" /></a><a href="http://3.bp.blogspot.com/-251zQrExdYk/UhTuG5Ffd3I/AAAAAAAAA7g/IJMeeJjEpSY/s1600/Foto-1376.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="150" src="https://3.bp.blogspot.com/-251zQrExdYk/UhTuG5Ffd3I/AAAAAAAAA7g/IJMeeJjEpSY/s200/Foto-1376.jpg" width="200" /></a></div>
<br />
<br />
<br />
<a href="http://1.bp.blogspot.com/-Rb2DRmeUd-c/UhTuIPxbtpI/AAAAAAAAA8E/KZwB2WE1Ai0/s1600/Foto-1379.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="150" src="https://1.bp.blogspot.com/-Rb2DRmeUd-c/UhTuIPxbtpI/AAAAAAAAA8E/KZwB2WE1Ai0/s200/Foto-1379.jpg" width="200" /></a> In the top-right picture, you can see quite well the spot where I put all the cable endpoints. There's a small "box" where a relais is located for the scooter's park-mode. Luckily, the box is too big for the relais alone, and can easily fit the TI launchpad and some other parts.<br />
<br />
In this step, I just put all the cables there (making sure they didn't short-circuit!)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-X_MJq5raig8/UhZKkm15j5I/AAAAAAAABSQ/DAOsBhrCUSc/s1600/Foto-1386.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="150" src="https://3.bp.blogspot.com/-X_MJq5raig8/UhZKkm15j5I/AAAAAAAABSQ/DAOsBhrCUSc/s200/Foto-1386.jpg" width="200" /></a></div>
<br />
Later, I removed the isolation from the cables again (carefully making sure nothing short-circuited, as you can see in the picture to the right), to solder them to flat cable. (To connect to the prototype PCB).<br />
<br />
<br />
<br />
<br />
4. Choosing a cable connected to the scooter ignition key as a power source<br />
<br />
This came as an afterthought, but if you connect the DC-DC converter to the 12V (or 24) directly, it'll be on, all the time. Not a big deal (hardly uses power), except that it the LCD really starts to draw attention in the middle of the night. A simple fix is attaching the V+ not directly to the battery, but to a circuit connected to the ignition key.<br />
<br />
Turn's out that in that little box I was working, that cable was present:) Took me a bit of reverse-engineering, but this is what the 4 cables of the relais are connected to:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-R4O7yhDgN2E/UhZQvmB6ZiI/AAAAAAAABS0/1mmIA_lIGbQ/s1600/relais-connections.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="207" src="https://1.bp.blogspot.com/-R4O7yhDgN2E/UhZQvmB6ZiI/AAAAAAAABS0/1mmIA_lIGbQ/s400/relais-connections.png" width="400" /></a></div>
<br />
If you press the (hydraulic) brake, the brakelight goes on, but also your accelerator doesn't work anymore.<br />
If you press the "park" button, the relais fires, and the brake light goes on all the time (and the accelerator doesn't work anymore)<br />
<br />
After a few measurements, the schematic above is what I came up with.<br />
<span style="font-size: x-small;">(I wanted to know all connections, because I also use the ground pin from there. I needed to make sure everything still worked in 'park-mode')</span><br />
<br />
<br />
<br />
<span style="font-size: large;">The Prototype PCB</span><br />
<br />
Fitting the breadboard prototype into the scooter was a bit unpractical.<br />
<br />
For one, it was just too big to fit into what seemed to the ideal place for the electronics. Secondly, you loose a good breadboard. Third, it's not exactly the most "sturdy" construction.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-mQEc_YJBggg/UhY_qAk4nYI/AAAAAAAABRs/qMf21HwJUY0/s1600/Foto-1384.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="150" src="https://4.bp.blogspot.com/-mQEc_YJBggg/UhY_qAk4nYI/AAAAAAAABRs/qMf21HwJUY0/s200/Foto-1384.jpg" width="200" /></a></div>
Hence, thanks to a hint, I went for the prototype PCB. (A PCB filled with metalized holes, in which you can fit components, wires, pinheaders, etc..)<br />
<br />
On the left, you can check out the result. (Which really took quite a bit of soldering!)<br />
<br />
<br />
<br />
<a href="http://4.bp.blogspot.com/-ye1CL8I-T-I/UhY_qDT47ZI/AAAAAAAABRw/h7VLHpEGXfE/s1600/Foto-1385.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="150" src="https://4.bp.blogspot.com/-ye1CL8I-T-I/UhY_qDT47ZI/AAAAAAAABRw/h7VLHpEGXfE/s200/Foto-1385.jpg" width="200" /></a><br />
Note that I just glued the DC-DC converter onto it:)<br />
You can also make out the resistor dividers from the picture.<br />
<br />
Note the pinheaders. Instead of just soldering the cables of the battery directly onto the PCB, I first soldered them to a flat-cable. On the PCB, you then just solder some pinheaders. Same for the cables that go to the LCD. Finally for the TI Launchpad, if you put the pinheaders at the correct spot, it just clicks into place:)<br />
<span style="font-size: x-small;"><br /></span>
<span style="font-size: x-small;">(Note that I actually wrongly 2strips of pinheaders, but was too lazy to remove them:) The one left-up is for the LCD, left down for the Scooter-Battery, right-up & down for the TI launchpad, and right-middle = not connected)</span><br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-VffCpOfY-qg/UhZBTiafgHI/AAAAAAAABR8/jPsjisx05sA/s1600/Foto-1383.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="240" src="https://1.bp.blogspot.com/-VffCpOfY-qg/UhZBTiafgHI/AAAAAAAABR8/jPsjisx05sA/s320/Foto-1383.jpg" width="320" /></a></div>
<br />
The picture on the right actually shows quite well how the system works. You can see the LCD & the connected flat cable, the Launchpad (connected via USB to my PC), and the prototype PCB.<br />
(The flat-cable connection to the batteries is not attached here)<br />
<br />
<span style="font-size: x-small;">(The breadboard is just on the desk, but is not connected anymore)</span><br />
<span style="font-size: x-small;"><br /></span>
<span style="font-size: x-small;"><br /></span>
<span style="font-size: x-small;"><br /></span>
<span style="font-size: x-small;"><br /></span>
<span style="font-size: x-small;"><br /></span>
When testing the prototype PCB at 12+V with the LCD or launchpad attached, <b>things tend to blow up</b> if you get it wrong..<br />
<b>Hint:</b><b style="font-size: x-large;"> </b> Try to design the PCB so that you clearly separate high-voltage connections from low-voltage connections.<br />
If you clearly separate the high-voltage pins from the rest, you can spend extra attention when handling them, making errors less likely<br />
<br />
<span style="font-size: x-small;">If you short-circuit any 3.3V pin, most likely not much will happen. The LCD uses 5V, but most of the pins of the launchpad are even 5V tolerant. This means that if you by accident short-circuit any of those cables, you're probably fine. However, make contact between a 12V pin anything else, and things start to burn.</span><br />
<br />
<br />
<span style="font-size: large;">Putting it together</span><br />
<span style="font-size: large;"><br /></span>
By far the most fun part, and the most stressy too! If you get it wrong, you blow up stuff, and you're set back again at least a few hours. Thankfully, aside from 1 microcontroller, I didn't loose too much:)<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-gQlz_-GP8ds/UhZSJl2hgOI/AAAAAAAABTA/q7dsEDGJgLQ/s1600/Foto-1389.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="150" src="https://3.bp.blogspot.com/-gQlz_-GP8ds/UhZSJl2hgOI/AAAAAAAABTA/q7dsEDGJgLQ/s200/Foto-1389.jpg" width="200" /></a></div>
<br />
<br />
<br />
Attaching the PCB to the LCD & scooter.<br />
<span style="font-size: large;"><br /></span>
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-WFqwKeM7FG0/UhZSbicTpaI/AAAAAAAABTI/Gsy3cH-BqgY/s1600/Foto-1392.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="150" src="https://4.bp.blogspot.com/-WFqwKeM7FG0/UhZSbicTpaI/AAAAAAAABTI/Gsy3cH-BqgY/s200/Foto-1392.jpg" width="200" /></a></div>
<br />
<br />
<br />
Hooking up the TI Launchpad<br />
<br />
<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-oMDMlXJeyoY/UhZSd4PELlI/AAAAAAAABUU/tqOwUdn4NtM/s1600/Foto-1432.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="150" src="https://1.bp.blogspot.com/-oMDMlXJeyoY/UhZSd4PELlI/AAAAAAAABUU/tqOwUdn4NtM/s200/Foto-1432.jpg" width="200" /></a></div>
<br />
Hooking up the LCD to the dashboard for a testdrive<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<br />
Doing the first testdrive:)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dxab1xE3pnWeZnqnxuWH3rc75qIP4qi39Ra_ipkZP7gbQKFQsUVvKkDhn1BlOeipaA16XR4fbb5CDamzayeYw' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div>
<br />
<br />
And some basic tests:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dxbEMr74D8UMzwiqoof8BP-lv1og6sCRXNjy7TcGkeboN0x4LB-iADd_Zbz1EFFEDmWHG2gPrg4tUMfUsqrJA' class='b-hbp-video b-uploaded' frameborder='0'></iframe><br />
<br />
<br />
Finally I mounted the LCD onto the dashboard (which took a bit of work too) :<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-aez0fGTwmWc/UhZSj7_NoRI/AAAAAAAABWU/45p3AkLBXwI/s1600/Foto-1451.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="240" src="https://4.bp.blogspot.com/-aez0fGTwmWc/UhZSj7_NoRI/AAAAAAAABWU/45p3AkLBXwI/s320/Foto-1451.jpg" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-LrMxEf8k-fU/UhZSnXvz83I/AAAAAAAABXg/PdQ4GCzo_ho/s1600/Foto-1460.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="240" src="https://1.bp.blogspot.com/-LrMxEf8k-fU/UhZSnXvz83I/AAAAAAAABXg/PdQ4GCzo_ho/s320/Foto-1460.jpg" width="320" /></a></div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
And finally with a bit of tape to cover up the LCD (+ some glue to keep it waterproof), you get the final result:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dyoAn0i7iOYlJCsrcWER01CuUeoh_MOxDCiKnAFiVWK3yyvkXN3wUzaFVyO-73E-3tG8SeSLxXzxeTUol-x7Q' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div>
<br />
<br />
<br />
<br />
<br />arre234http://www.blogger.com/profile/04807961375666237936noreply@blogger.com0