tag:blogger.com,1999:blog-89790454963874557852024-03-13T08:51:42.561+01:00starlightblog of Joost Yervante DamadAnonymoushttp://www.blogger.com/profile/09143890844136884489noreply@blogger.comBlogger223125tag:blogger.com,1999:blog-8979045496387455785.post-79093887096197079842017-09-08T09:29:00.000+02:002017-09-08T09:29:06.814+02:00fixing Hue persistence using async IO in Rust / Futures<h4>
Intro</h4>
<br />
I have two Philips Hue lamps and mostly like them when they are in the very warm white (2000k) color temperature setting.<br />
The problem is that the setting does not persist when the lamps are switched using a physical power switch. To solve this I wrote the <a href="https://github.com/andete/hue_persistence" target="_blank">Hue Persistence</a> program last year.<br />
This program runs on the LAN and basically polls and stores the lamp settings and when it it detects a lamp going from off to on it restores the last setting.<br />
<br />
After using it for a few weeks it became clear that there is one big problem with it: the Philips Hue hub sometimes accepts a connection from my program but then does not respond, yet keeps the connection open.<br />
As the program is written using synchronous IO, this causes the program to hang forever, and it doesn't work anymore.<br />
<br />
<h4>
Solution</h4>
<br />
The Hue Persistence program uses the <a href="https://github.com/Orangenosecom/philipshue" target="_blank">Rust Philips Hue</a> library which using <a href="https://hyper.rs/" target="_blank">Hyper</a> as a HTTP client to talk to the Philips Hue hub via it's restful API.<br />
This library still uses Hyper 0.10 which does not provide async IO yet.<br />
<br />
Recently there has been a lot of work for asynchronous IO in rust using <a href="https://tokio.rs/" target="_blank">Tokio</a> and <a href="https://docs.rs/futures/0.1.15/futures/" target="_blank">Futures</a>. Version 0.11 of Hyper uses this.<br />
<br />
First thing I had to do is port the Rust Philips Hue library to use Hyper 0.11 and thus async IO. This turned out to be quite an undertaking. The result of this can be found on the <a href="https://github.com/andete/philipshue/tree/hyper_0.11" target="_blank">hyper_0.11 branch</a> of my fork of the library. It is still a bit ugly, but works.<br />
<br />
So far I've found using Futures for async IO to have the following issues:<br />
<br />
<ul>
<li>error handling can be very confusing; error types need to be the same in future composition and you have to explicitly do error type conversions to make things work</li>
<li>future composition results in complex types, returning to Box<Future> helps a bit, but it still can be rather confusing (I didn't try the not yet released <a href="https://github.com/rust-lang/rust/issues/34511" target="_blank">impl Trait</a> solution)</li>
<li>it's not so obvious which future composition methods to use when, docs are sparse</li>
<li>branching (if, ...) inside futures is tedious again because of types having to match perfectly</li>
</ul>
<div>
In the end though I got the satisfaction of a working async library, after which I updated the Hue Persistence app to have a timeout on it's requests. This again turned out to be really tedious.</div>
<div>
I had to use select2 with a sleep instead of <a href="https://docs.rs/tokio-timer/0.1.2/tokio_timer/struct.Timer.html#method.timeout" target="_blank">tokio_timer::Timer::timeout()</a> because it was just impossible to get the types to work for the error types when using <a href="https://docs.rs/tokio-timer/0.1.2/tokio_timer/struct.Timer.html" target="_blank">tokio_timer::Timer</a>, due to the TimeoutError containing Future type as a containing type in the signature of timeout().</div>
<div>
<br /></div>
<h4>
<b>Conclusion</b></h4>
<div>
<br /></div>
<div>
My lamps are behaving fine now!</div>
<div>
<br /></div>
<div>
Async IO in Rust using Futures/tokio is interesting but at this point it still feels like "getting the types right" is somewhat in the way of normal coding productivity.</div>
<div>
Some ergonomic improvements/language support could surely be used.</div>
<div>
To be revisited in the Future (pun intended ;) ).</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
Anonymoushttp://www.blogger.com/profile/16901177343869803451noreply@blogger.com0tag:blogger.com,1999:blog-8979045496387455785.post-6320698141240241232017-06-17T10:08:00.000+02:002017-06-17T10:08:41.383+02:00implementing a simple language switch using rocket in rustLet's look how easy it is to implement a simple cookie based language switch in the<a href="https://rocket.rs/" target="_blank"> rocket web framework</a> for the <a href="https://www.rust-lang.org/" target="_blank">rust programming language</a>.
Defining the language type:<br />
<br />
<script src="https://gist.github.com/andete/dfcf0dd72cc59cba4f4896af75c5f06d.js"></script>
In this case there will be support for Dutch and English. <i>PartialEq</i> is derived to be able to compare Lang items with ==.
<br />
<br />
The<i> Default</i> trait is implemented to define the default language:<br />
<br />
<script src="https://gist.github.com/andete/9f48e995ff9e8470e7320154143a1cae.js"></script>
The <i>FromStr</i> trait is implemented to allow creating a <i>Lang</i> item from a string.<br />
<br />
<script src="https://gist.github.com/andete/ee8e5c6e3e3f01ad63a41464b309dcdd.js"></script>
The <i>Into<&'static str></i> trait is added to allow the conversion in the other direction.<br />
<br />
<script src="https://gist.github.com/andete/610c2d3da5a89d342288dadc0214c537.js"></script>
Finally the <i>FromRequest</i> trait is implemented to allow extracting the "lang" cookie from the request.
<br />
<br />
<script src="https://gist.github.com/andete/b5ce0851041546449f3d577b520cb4f9.js"></script>
It always succeeds and falls back to the default when no cookie or an unknown language is is found.
How to use the <i>Lang</i> constraint on a request:
<br />
<br />
<script src="https://gist.github.com/andete/56bfafbb97f5d505f16169b5efd2fd8e.js"></script>
And the language switch page:<br />
<br />
<script src="https://gist.github.com/andete/43aee9db7542dd8dc33d46c371a7dcbe.js"></script>
And as a cherry on the pie, let's have the language switch page automatically redirect to the referrer. First let's implement a <i>FromRequest</i> trait for our own <i>Referer</i> type:
<br />
<br />
<script src="https://gist.github.com/andete/7572bfddf3503f7f9b8f09c0157d90e9.js"></script>
When it finds a Referer header it uses the content, else the request is forwarded to the next handler. This means that if the request has no Referer header it is not handled, and a 404 will be returned.
<br />
Finally let's update the language switch request handler:<br />
<br />
<script src="https://gist.github.com/andete/f9307b822ab818219be2e5e2da5bf5ab.js"></script>
Pretty elegant.
A recap with all code combined and adding the missing glue:
<br />
<br />
<script src="https://gist.github.com/andete/02975114ecf5b1014d66a2c33cb48540.js"></script>Anonymoushttp://www.blogger.com/profile/16901177343869803451noreply@blogger.com0tag:blogger.com,1999:blog-8979045496387455785.post-30146568080195787682017-01-29T09:30:00.003+01:002017-01-29T09:30:45.546+01:00making a HP Color LaserJet printer wireless with a Raspberry Pi 3 <div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1qEM48RLh7zUPYyAXzxPiegULqpHZQikwqcUKxxk9njJrcGiJ1ZO37lJgwjqPKfQjzFyqYgvd2U_sJdat8h-N-9R0fw4MB-mwgD2h2o6TXp54s3BqQFIfeKwYSzHnFRSUic-y5EzXL8Q/s1600/IMG_20170129_092539.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1qEM48RLh7zUPYyAXzxPiegULqpHZQikwqcUKxxk9njJrcGiJ1ZO37lJgwjqPKfQjzFyqYgvd2U_sJdat8h-N-9R0fw4MB-mwgD2h2o6TXp54s3BqQFIfeKwYSzHnFRSUic-y5EzXL8Q/s320/IMG_20170129_092539.jpg" width="240" /></a></div>
<br />
<br />
My old HP Color LaserJet 2820 is still working great, however it only supports being connected via ethernet or USB. As a workaround I've been using "Power Line Communication" to bridge directly from my router to the printer over the electrical wires.<br />
Recently I've been revamping the home network and wanted to get rid of these last power line connections. Ideally I'd want the printer to join the wireless network.<br />
<br />
The arrival of the Raspberry Pi 3 with builtin WiFi seems like a good opportunity to implement this.<br />
The raspberry Pi is connected with it's Ethernet port to the printer. The WiFi is connected to the local LAN where I configured the router to give it a fixed IP address.<br />
<br />
<h4>
Approach 1: Cups printer server</h4>
<br />
I install the cupsys printing system on the Raspberry Pi, and configure it to properly support the printer (using HPLIP). Besides that, I install a DHCP server to serve the printer an IP address on it's own private network: The cable between Raspberry Pi and printer.<br />
I change the configuration of the printer in Cups on the Raspberry Pi to make the printer shared on the LAN.<br />
Now all other computers can just use that shared printer to print.<br />
This works really good for printing, however it doesn't work at all for scanning.<br />
When scanning the scanning software (SANE) seems to want to connect directly to the printer and this of course isn't possible when the printer is on a different network and there is no routing.<br />
<br />
<h4>
Approach 2: Routing</h4>
<br />
I updated the Raspberry Pi to do routing, by enabling IP forwarding.<br />
(uncomment the <span style="font-family: "courier new" , "courier" , monospace;">net.ipv4.ip_forward=1</span> line in<span style="font-family: "courier new" , "courier" , monospace;"> /etc/sysctl.conf</span> )<br />
I also configure my router with an extra route to have it know about the network that is now reachable via the Raspberry Pi.<br />
Now the printer can be directly communicated with. This allows me to configure the printer directly again on my Linux laptop.<br />
Printing still works fine. However scanning still doesn't work.<br />
When I tell the scanner software the IP address of the printer explicitly, it sometimes works, but most of the time it doesn't work at all.<br />
My guess is that the scanner software relies on some communication that doesn't work outside it's own network.<br />
<br />
<b>Approach 3: Proxy ARP</b><br />
<br />
To learn more about the technicalities of proxy ARP, read <a href="https://en.wikipedia.org/wiki/Proxy_ARP">here on Wikipedia</a>, and <a href="https://wiki.debian.org/BridgeNetworkConnectionsProxyArp">here on wiki.debian.org</a>. In summary it is a trick that makes it seem to the rest of the network that the Raspberry Pi and the printer are the same.<br />
In order for this to work I want the printer to have an address in the same network as the local net.<br />
First remove the DHCP server installed for the previous approaches, then install a DHCP proxy. This is easily installed (<span style="font-family: "courier new" , "courier" , monospace;">apt-get install dhcp-helper</span>) and configured (<span style="font-family: "courier new" , "courier" , monospace;">DHCPHELPER_OPTS="-b wlan0"</span> in <span style="font-family: "courier new" , "courier" , monospace;">/etc/default/dhcp-helper</span>).<br />
There are multiple ways to enable Proxy ARP. The easiest is to install (<span style="font-family: "courier new" , "courier" , monospace;">apt-get install parprouted</span>) and configure it.<br />
My /etc/network/interfaces now looks like this:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">auto lo<br /> iface lo inet loopback<br />auto eth0<br /> allow-hotplug eth0<br /> iface eth0 inet manual<br /> <br />allow-hotplug wlan0<br /> iface wlan0 inet dhcp<br /> wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf<br /> post-up /usr/sbin/parprouted eth0 wlan0<br /> post-down /usr/bin/killall /usr/sbin/parprouted<br /> post-up /sbin/ip addr add $(/sbin/ip addr show wlan0 | perl -wne 'm|^\s+inet (.*)/| && print $1')/32 dev eth0<br /> post-down /sbin/ifdown eth0 </span></blockquote>
<br /><br />With proxy ARP in place the printer still works great, and finally the scanner also works in a stable way.<br />
<h4>
<br />Alternative approaches</h4>
<br />
I could try hooking the printer to the Raspberry Pi via USB. As I've never used the printer in this way, I've not attempted this.Anonymoushttp://www.blogger.com/profile/16901177343869803451noreply@blogger.com0tag:blogger.com,1999:blog-8979045496387455785.post-61436323285021265362017-01-10T18:00:00.000+01:002017-01-10T18:00:06.077+01:00stable wifi on the shuttle xs36v with DebianThe Wifi connection of this machine is very slow, especially noticeable when logging in to the machine via ssh.<br />
The solution is to follow the notes on <a href="https://wiki.debian.org/rtl819x">https://wiki.debian.org/rtl819x</a> , copied here:<br />
<span style="background-color: white; color: #222222; font-family: sans-serif; font-size: 16px;"><br /></span>
<span style="background-color: white; color: #222222; font-family: sans-serif; font-size: 16px;">Devices supported by this driver may suffer from intermittent connection loss. If so, it can be made more reliable by disabling power management via module options </span><tt class="backtick" style="border: 0px; font-size: 13px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">ips</tt><span style="background-color: white; color: #222222; font-family: sans-serif; font-size: 16px;">and</span><span style="background-color: white; color: #222222; font-family: sans-serif; font-size: 16px;"> </span><tt class="backtick" style="border: 0px; font-size: 13px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">fwlps</tt><span style="background-color: white; color: #222222; font-family: sans-serif; font-size: 16px;">. These can be supplied by creating a new file:</span><br />
<div class="line862" style="background-color: white; border: 0px; color: #222222; font-family: sans-serif; font-size: 16px; margin-bottom: 1.5em; margin-top: 1.5em; outline: 0px; padding: 0px; vertical-align: baseline;">
<span class="anchor" id="line-113" style="border: 0px; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"></span></div>
<div class="line867" style="background-color: white; border: 0px; color: #222222; font-family: sans-serif; font-size: 16px; margin-bottom: 1.5em; margin-top: 1.5em; outline: 0px; padding: 0px; vertical-align: baseline;">
<tt style="border: 0px; color: black; font-size: 13px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">/etc/modprobe.d/rtl8192ce.conf</tt><span class="anchor" id="line-114" style="border: 0px; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"></span></div>
<br />
<div class="line867" style="background-color: white; border: 0px; color: #222222; font-family: sans-serif; font-size: 16px; margin-bottom: 1.5em; margin-top: 1.5em; outline: 0px; padding: 0px; vertical-align: baseline;">
<span class="anchor" id="supported" style="border: 0px; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"></span><span class="anchor" id="line-119" style="border: 0px; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"></span></div>
<br />
<ul style="-webkit-text-stroke-width: 0px; background-color: white; border: 0px; color: #222222; font-family: sans-serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; letter-spacing: normal; list-style: disc; margin: 1.5em 0px; orphans: 2; outline: 0px; padding: 0px 0px 0px 1.5em; text-align: start; text-indent: 0px; text-transform: none; vertical-align: baseline; white-space: normal; widows: 2; word-spacing: 0px;">
<li style="border: 0px; font-family: inherit; font-size: 16px; font-style: inherit; font-weight: inherit; list-style-type: none; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"><span class="anchor" id="line-115" style="border: 0px; font-family: inherit; font-size: 16px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"></span><span class="anchor" id="line-116" style="border: 0px; font-family: inherit; font-size: 16px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"></span><pre style="background-color: #f5f6f7; border: 1px solid rgb(210, 211, 215); color: black; font-family: monospace; font-size: 13px; font-style: inherit; font-weight: inherit; line-height: 2em; margin: 2em 1.5em; outline: 0px; overflow: auto; padding: 1em; vertical-align: baseline; white-space: pre; word-wrap: break-word;"><span class="anchor" id="line-1-6" style="border: 0px; font-family: inherit; font-size: 13px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"></span>options rtl8192ce ips=0 fwlps=0</pre>
<span class="anchor" id="line-117" style="border: 0px; font-family: inherit; font-size: 16px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"></span><span class="anchor" id="line-118" style="border: 0px; font-family: inherit; font-size: 16px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"></span></li>
</ul>
<br />
<br />Anonymoushttp://www.blogger.com/profile/16901177343869803451noreply@blogger.com0tag:blogger.com,1999:blog-8979045496387455785.post-19822137519244215162017-01-05T10:22:00.003+01:002017-01-05T10:22:40.630+01:00Dirt Rally Timing LogIn order to keep track of my skill evolution playing the excellent rally sim game "Dirt Rally" I've set up a google sheet.<br />
<br />
This google sheet could be interesting for other people as well so I'm sharing it here. Note that this one has some example content only not my actual full content.<br />
<br />
To use it make a copy of it on your own drive.<br />
<br />
Have fun driving!<br />
<a href="https://www.blogger.com/goog_1306781421"><br /></a>
<a href="https://docs.google.com/spreadsheets/d/10PBtlXl5hZIIYa_ab8ypG8jnvuQcaN2hbM9BMtDsqmw/edit?usp=sharing">https://docs.google.com/spreadsheets/d/10PBtlXl5hZIIYa_ab8ypG8jnvuQcaN2hbM9BMtDsqmw/edit?usp=sharing</a>Anonymoushttp://www.blogger.com/profile/16901177343869803451noreply@blogger.com0tag:blogger.com,1999:blog-8979045496387455785.post-37747241779908187472016-12-09T10:02:00.003+01:002016-12-09T10:02:59.165+01:00Persistence for Philips HueTwo of the lights in our living are Philips Hue lights.<br />
I especially like them for their ability to reach 2000K color temperature (very warm white light), which gives a nice mellow yellowish white light.<br />
<br />
We control the lights via normal light switches contained in the light fixture.<br />
Due to the way Philips Hue lights work this implies that whenever we turn on the lights again they go back to the default setting of around 2700K (normal warm white).<br />
<br />
In order to fix this once and for all I wrote a little program in rust that does this:<br />
<br />
<ul>
<li>poll the state of the lights every 10 seconds (there is no subscribe/notify :( )</li>
<li>keep the light state in memory</li>
<li>if a light changes from unreachable (usually due to being turned off by the switch) to reachable (turned on by the switch), restore the hue to the last state before it became unreachable</li>
</ul>
<div>
Code is in rust (of course) and can be found at <a href="https://github.com/andete/hue_persistence">https://github.com/andete/hue_persistence</a>.</div>
<div>
<br /></div>
<div>
Just run it on a local server (I use my <a href="http://joost.damad.be/2016/12/working-console-on-shuttle-xs36v-mini.html">shuttle xs36v</a>) and it automatically starts working.</div>
<div>
Keep in mind that it can take up to a minute for the Hue system to detect that a light is reachable again.</div>
<div>
<br /></div>
<div>
A short video demoing the system in action:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<iframe width="320" height="266" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/t5LcDb8a308/0.jpg" src="https://www.youtube.com/embed/t5LcDb8a308?feature=player_embedded" frameborder="0" allowfullscreen></iframe></div>
<div>
<br /></div>
Anonymoushttp://www.blogger.com/profile/16901177343869803451noreply@blogger.com0tag:blogger.com,1999:blog-8979045496387455785.post-8854382401878138552016-12-02T12:19:00.002+01:002016-12-02T12:19:42.288+01:00working console on Shuttle xs36v mini computer with Debian 8 (Jesse)I recently re-installed this system to use it as a local server.<br />
<br />
Installation of Debian 8 went smooth. I choose not to install a graphical environment as I only want to attach a screen in emergency situations.<br />
<br />
The system boots fine but then the screen goes into power-safe mode. The system is still reachable remotely.<br />
<br />
After some searching on the internet <a href="https://ubuntuforums.org/showthread.php?t=2073727" target="_blank">[1]</a> the solution is to blacklist the graphics driver of the system.<br />
<br />
Create a file called <span style="font-family: "courier new" , "courier" , monospace;">/etc/modprobe.d/blacklist.conf</span> and add the following to it:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace;">blacklist gma500_gfx</span></blockquote>
This tells the system not to load the driver. Then do<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace;"> sudo update-initramfs -u</span></blockquote>
this updates the boot RAM disk to reflect the change.<br />
<br />
Reboot the system and enjoy a working console.<br />
<br />
Picture or it didn't happen:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJBbIjgK60fpZCvE_2Y_rO_aZNNNQ638Kh8Aw-4Q-NBLsYUjRUw5WASrf-dNVrbUbaDoFZPDe99sehUP8E9CSYE5BecnEV4BhnbLfpdjio_dy3i2UULy8Dj-_xf6xnWHhRnyJeqjbNxZe4/s1600/IMG_20161202_121504.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJBbIjgK60fpZCvE_2Y_rO_aZNNNQ638Kh8Aw-4Q-NBLsYUjRUw5WASrf-dNVrbUbaDoFZPDe99sehUP8E9CSYE5BecnEV4BhnbLfpdjio_dy3i2UULy8Dj-_xf6xnWHhRnyJeqjbNxZe4/s320/IMG_20161202_121504.jpg" width="239" /></a></div>
Anonymoushttp://www.blogger.com/profile/09143890844136884489noreply@blogger.com0tag:blogger.com,1999:blog-8979045496387455785.post-56086026977077034912014-03-07T10:46:00.002+01:002016-05-19T09:56:18.752+02:00Bluetooth Low Energy Explorer ToolBluetooth Low Energy is all about services and attributes. Exploring these attributes is an interesting way to gain more insight in how a device works and is invaluable for testing. In order to make this process more comfortable a testing tool is invaluable. Hence the BTLE-explorer was born.<br />
<br />
continue reading on the <a href="https://www.productize.be/bluetooth-low-energy-explorer-tool/" target="_blank">Productize Lab blog</a>.Anonymoushttp://www.blogger.com/profile/09143890844136884489noreply@blogger.com0tag:blogger.com,1999:blog-8979045496387455785.post-32438984076105427912014-05-13T18:17:00.002+02:002016-05-19T09:55:51.427+02:00a peek inside the shielding can of the Bluegiga BLE113 Bluetooth Low Energy moduleIn <a href="https://www.productize.be/a-peek-inside-the-shielding-can-of-the-bluegiga-ble113-bluetooth-low-energy-module/" target="_blank">this new blog post</a> I take a quick peek inside a broken BLE113 Bluetooth low energy module.Anonymoushttp://www.blogger.com/profile/09143890844136884489noreply@blogger.com0tag:blogger.com,1999:blog-8979045496387455785.post-75730952977496760812014-10-07T09:15:00.003+02:002016-05-19T09:55:28.782+02:00Driving WS2812 Programmable RGB LEDs using hardware SPINew blog post available at:<br />
<br />
<a href="https://www.productize.be/driving-ws2812-programmable-rgb-leds-using-hardware-spi/">https://www.productize.be/driving-ws2812-programmable-rgb-leds-using-hardware-spi/</a>Anonymoushttp://www.blogger.com/profile/09143890844136884489noreply@blogger.com0tag:blogger.com,1999:blog-8979045496387455785.post-48113438506776690422013-08-13T19:50:00.000+02:002014-03-02T15:22:14.260+01:00Experiments with Bluetooth Low Energy (4.0) under LinuxWith iPhônes liberated from the apple authentication chip by it, and Android also having added support in the latest Android 4.3, Bluetooth Low Energy (4.0) is starting to look more interesting.<br />
<br />
In this blog post I'm going to use a <a href="https://www.tindie.com/products/andete/bluetooth-smart-ready-btbtle-bluegiga-bt111-a-usb-dongle/" target="_blank">bluegiga BT111 based USB bluetooth dongle</a> on Linux as a client and a <a href="http://www.ti.com/ww/en/wireless_connectivity/sensortag/" target="_blank">TI CC2541 SensorTag</a> as server.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLtkvd1JFnWDot9mf8cIIuyyBRpjB9XjTZnzCGmg117EFddvpp5smcrEjs5Jv8xctLEqrqNej-WtznVNQM3_hqVvR-dM3WIEoW_5cvNoX8lJxxGQ3Bm2lC3ucIC3bwQa5UMNK2nsMj934v/s1600/in_computer1.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLtkvd1JFnWDot9mf8cIIuyyBRpjB9XjTZnzCGmg117EFddvpp5smcrEjs5Jv8xctLEqrqNej-WtznVNQM3_hqVvR-dM3WIEoW_5cvNoX8lJxxGQ3Bm2lC3ucIC3bwQa5UMNK2nsMj934v/s640/in_computer1.jpg" height="424" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">USB dongle in computer</td></tr>
</tbody></table>
The SensorTag is a nice little bluetooth 4 example device provided by Texas Instruments.<br />
<br />
<h3>
Device</h3>
<div>
First step is put the device in the computer. As my laptop already has an existing bluetooth device build-in, the new one will enumerate as "hci1". This can be found out also by using hcitool.</div>
<div>
<br /></div>
<div>
<br /></div>
<pre class="prettyprint">$ hcitool dev
Devices:
hci1 00:07:80:60:CE:4D
hci0 EC:55:F9:F4:A0:xx
</pre>
<br />
In this case the bluetooth mac address of the BT111 is 00:07:80:60:CE:4D.<br />
<br />
<h3>
Scanning for a device</h3>
<div>
Normal bluetooth scanning is done with hcitool scan. Low Energy scanning is done with hcitool lescan.</div>
<div>
Make sure to press the button on the side of the SensorTag first to make it discoverable. Scanning is continuous to stop it with Ctrl-C. Low Energy devices require root access hence the sudo. I would expect being in the bluetooth group to be enough but for some reason it isn't.</div>
<div>
<br /></div>
<div>
<br /></div>
<pre class="prettyprint">$ sudo hcitool -i hci1 lescan
LE Scan ...
BC:6A:29:AC:2E:B4 (unknown)
BC:6A:29:AC:2E:B4 SensorTag
BC:6A:29:AC:2E:B4 (unknown)
BC:6A:29:AC:2E:B4 SensorTag
BC:6A:29:AC:2E:B4 (unknown)
^C
</pre>
<br />
<h3>
Using gatttool to access the device</h3>
<div>
Now we know the address of the SensorTag: BC:6A:29:AC:2E:B4. In contrast with regular Bluetooth where there are a whole range of protocols, with Bluetooth Low Energy there is only one protocol at the top and it is GATT (Generic Attribute).</div>
<div>
<br /></div>
<div>
The actual functionality of a device is implemented by means of attributes which can be read, written to or notification/indication enabled for, depending on the attribute.</div>
<div>
<br /></div>
<div>
gatttool is a simple Linux tool that can be used to manipulate these attributes with a Bluetooth Low Energy device. It can be used as a simple command line tool but I find it easier to use it in it's interactive mode.</div>
<div>
<br /></div>
<div>
Let's enter the interactive mode.</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<pre class="prettyprint">$ sudo gatttool -i hci1 -b BC:6A:29:AC:2E:B4 -I
[ ][BC:6A:29:AC:2E:B4][LE]>
</pre>
<br />
It returns us a prompt. Let's connect to the device.
<br />
<br />
<br />
<pre class="prettyprint">[ ][BC:6A:29:AC:2E:B4][LE]> connect
[CON][BC:6A:29:AC:2E:B4][LE]>
</pre>
<br />
The CON indication tells us that the connection is established.
<br />
Now the primary command can be used to find the primary services of the device.<br />
<br />
<pre class="prettyprint">[CON][BC:6A:29:AC:2E:B4][LE]> primary
[CON][BC:6A:29:AC:2E:B4][LE]>
attr handle: 0x0001, end grp handle: 0x000b uuid: 00001800-0000-1000-8000-00805f9b34fb
attr handle: 0x000c, end grp handle: 0x000f uuid: 00001801-0000-1000-8000-00805f9b34fb
attr handle: 0x0010, end grp handle: 0x0022 uuid: 0000180a-0000-1000-8000-00805f9b34fb
attr handle: 0x0023, end grp handle: 0x002a uuid: f000aa00-0451-4000-b000-000000000000
attr handle: 0x002b, end grp handle: 0x0035 uuid: f000aa10-0451-4000-b000-000000000000
attr handle: 0x0036, end grp handle: 0x003d uuid: f000aa20-0451-4000-b000-000000000000
attr handle: 0x003e, end grp handle: 0x0048 uuid: f000aa30-0451-4000-b000-000000000000
attr handle: 0x0049, end grp handle: 0x0054 uuid: f000aa40-0451-4000-b000-000000000000
attr handle: 0x0055, end grp handle: 0x005c uuid: f000aa50-0451-4000-b000-000000000000
attr handle: 0x005d, end grp handle: 0x0061 uuid: 0000ffe0-0000-1000-8000-00805f9b34fb
attr handle: 0x0062, end grp handle: 0x0068 uuid: f000aa60-0451-4000-b000-000000000000
attr handle: 0x0069, end grp handle: 0xffff uuid: f000ffc0-0451-4000-b000-000000000000
</pre>
<br />
Attributes in GATT have uuids and handles. UUIDs (unique identifiers) define a certain type of entry, handles can be used to access a value. To make things more complicated there is also nesting involved.
Certain UUIDs are defined in the standard and always have to be provided. Others can just be vendor specific and provide the actual data for the service. It's beyond the scope of this blog post to further look into how all that fits together.
<br />
<br />
<h3>
SensorTag attributes</h3>
<div>
Luckily for us, the meaning of the sensortag attributes are defined on the user guide at <a href="http://processors.wiki.ti.com/index.php/SensorTag_User_Guide" target="_blank">http://processors.wiki.ti.com/index.php/SensorTag_User_Guide</a>.</div>
<div>
<br /></div>
<div>
For this blog I'm looking at the humidity sensor as it is the easiest and the values shown in the document are actually correct :) <a href="http://processors.wiki.ti.com/index.php/SensorTag_User_Guide#Humidity_Sensor_2" target="_blank">http://processors.wiki.ti.com/index.php/SensorTag_User_Guide#Humidity_Sensor_2</a></div>
<div>
<br /></div>
<div>
As you can see on that page, there are 3 important handles for the humidity sensor, Data (0x38), DataNotification (0x39) and Config (0x3C).<br />
<br />
Let's try reading from the Data handle:<br />
<br /></div>
<pre class="prettyprint">[CON][BC:6A:29:AC:2E:B4][LE]> char-read-hnd 38
[CON][BC:6A:29:AC:2E:B4][LE]>
Characteristic value/descriptor: 00 00 00 00
</pre>
<br />
So far so good, but no useful data. We first need to enable the sensor. This is done by writing 1 in the Config handle.
<br />
<br />
<pre class="prettyprint">[CON][BC:6A:29:AC:2E:B4][LE]> char-write-req 3c 01
[CON][BC:6A:29:AC:2E:B4][LE]> Characteristic value was written successfully
</pre>
<br />
Let's retry reading the value now.
<br />
<br />
<pre class="prettyprint">[CON][BC:6A:29:AC:2E:B4][LE]> char-read-hnd 38
[CON][BC:6A:29:AC:2E:B4][LE]>
Characteristic value/descriptor: 68 68 4e 72
</pre>
<br />
That's more like it.
Using the math provided on the website and a python script, this gives the temperature and the humidity.<br />
<br />
<pre class="prettyprint">>>> -46.85 + 175.72/65536 * 0x6868
24.8151025390625
>>> -6.0 + 125.0/65536 * (0x72e4 & ~3)
50.09893798828125
</pre>
<br />
So 25 Celsius and 50% humidity. That agrees with my local weather sensor. Nice :)<br />
<br />
Instead of reading values it is also possible to use notifications.<br />
<br />
<br />
<pre class="prettyprint">[CON][BC:6A:29:AC:2E:B4][LE]> char-write-req 39 0100
[CON][BC:6A:29:AC:2E:B4][LE]> Characteristic value was written successfully
Notification handle = 0x0038 value: 68 68 f6 71
[CON][BC:6A:29:AC:2E:B4][LE]>
...
</pre>
This will provide the temperature and the humidity every second automatically. Let's disable it again it is spamming me :)<br />
<br />
<pre class="prettyprint">[CON][BC:6A:29:AC:2E:B4][LE]> char-write-req 39 0000
[CON][BC:6A:29:AC:2E:B4][LE]> Characteristic value was written successfully
</pre>
<br />
Finally let's disable the sensor and disconnect.
<br />
<br />
<pre class="prettyprint">[CON][BC:6A:29:AC:2E:B4][LE]> char-write-req 3c 00
[CON][BC:6A:29:AC:2E:B4][LE]> Characteristic value was written successfully
[CON][BC:6A:29:AC:2E:B4][LE]> disconnect
[ ][BC:6A:29:AC:2E:B4][LE]>
</pre>
<br />
<h3>
Conclusion</h3>
<div>
Bluetooth Low Energy might look a bit different/strange at first but it is really quite nice! I'm certainly going to explore it further!</div>
<div>
<br /></div>
<h3>
Shameless plug!</h3>
<div>
<b>Don't forget to check out the very nice BT111 based USB dongle available for sale at <a href="https://www.tindie.com/stores/andete/" target="_blank">my tindie store!</a></b></div>
<div>
<b><br /></b></div>
<div class="separator" style="clear: both; text-align: center;">
<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzfiSWuaovha9MH4YGG4znfdGpQTeSHMbwx3hdP8QuXJJJiMB2Q33wFYTwH_xfmfvQvMnaajonIY4seeAmAteUCV0DYRw0VUrcCJFdgEI3dNuDwK3NLHDeVP6usbGrkp8dbHLTOvI1CDZk/s400/front.jpg" height="250" width="400" /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOmh90NUz5qhnICSiaVywOgjtzvC2Otr1fGBpZqO32S7plrJ6Y1NPgZIUfeE0D0XH96ZOadlaAaUbrfDhRGd9lPyd_ynfVPR21CmR_1Laz2-rKrcsO96sixg7OAt1DrmSJCs5T8mUX5JWB/s1600/in_computer.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOmh90NUz5qhnICSiaVywOgjtzvC2Otr1fGBpZqO32S7plrJ6Y1NPgZIUfeE0D0XH96ZOadlaAaUbrfDhRGd9lPyd_ynfVPR21CmR_1Laz2-rKrcsO96sixg7OAt1DrmSJCs5T8mUX5JWB/s400/in_computer.jpg" height="223" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div>
<b><br /></b></div>
Anonymoushttp://www.blogger.com/profile/09143890844136884489noreply@blogger.com3tag:blogger.com,1999:blog-8979045496387455785.post-51723413750259114302013-11-29T10:58:00.000+01:002014-03-02T15:21:56.445+01:00using efm32 simplicitystudio under Linux<h2>
Intro</h2>
<br />
So I went to a workshop yesterday mostly about the Silabs/Energy Micro micro-controllers. The workshop was rather interesting, but the workshop was done with the tools in Windows 7. As I'm working almost exclusively under Linux since 1998, this was quite a painful experience for me. Especially USB device handling is so much smoother in Linux. But enough about my windows pain. The EFM32 micro-controllers are based around ARM Cortex and seem to be genuinely nice ICs with a bunch of special low-power features. I'm not going to list all those as this is not a marketing post, you can find enough information about that on the internet already.<br />
<br />
I came back home with two very nice dev-boards, which is pretty cool in itself!<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpq7WahwPuS7O4tx7KP5JXwrHPOMY0jM63qD1xRwiWe3OXTyGaVwrdZyPT0pX_7u-3E6Ot-lajAhXi2HDs6Lv04GI6fTlFYwoGXtrvFH3MGtOwSIrkEZ9qlNF-xADm3vZfXpfWPNrvizSh/s1600/space_invaders.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpq7WahwPuS7O4tx7KP5JXwrHPOMY0jM63qD1xRwiWe3OXTyGaVwrdZyPT0pX_7u-3E6Ot-lajAhXi2HDs6Lv04GI6fTlFYwoGXtrvFH3MGtOwSIrkEZ9qlNF-xADm3vZfXpfWPNrvizSh/s400/space_invaders.JPG" height="205" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">EFM32 ZERO GECKO running a nice Space Invaders clone demo</td></tr>
</tbody></table>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCTnJFiwZYG_WjnB-VKUMGiurrL_9DhuZgi88Vu4zEwaWRjH8sh8ouE6d7p7QSvjb4WvLi49u1_j8pBh_zH6ShTWVfQok5c5iBMk4guU0OORfp7VSWefT_r90B7BGd2eyGeigUHzyer3Zn/s1600/light_sense.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCTnJFiwZYG_WjnB-VKUMGiurrL_9DhuZgi88Vu4zEwaWRjH8sh8ouE6d7p7QSvjb4WvLi49u1_j8pBh_zH6ShTWVfQok5c5iBMk4guU0OORfp7VSWefT_r90B7BGd2eyGeigUHzyer3Zn/s400/light_sense.JPG" height="198" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">EFM32 WONDER GECKO running a light sense demo</td></tr>
</tbody></table>
<br />
<br />
<h2>
Linux</h2>
When I arrived back home I started reading up a bit more about the ICs and one of the first things I found in a vid on youtube is that the simplicity studio is also available for Linux and OSX.<br />
<br />
Going to the silabs download website only gave a download for windows, but a quick google brought me to the <a href="http://forum.energymicro.com/forum/46-toolsfirmware-beta/" target="_blank">Energy Micro forum</a> where there is a <a href="http://forum.energymicro.com/topic/990-simplicity-studio-120-energyaware-tools-osx-linux/" target="_blank">beta download</a> or simplicity studio for Linux and OSX available. After a few tricks it works smoothly in Linux, if only I had known that a day sooner ;)<br />
<br />
<h2>
Installation</h2>
<div>
What I did to get a working installation on on my x86-64 Debian Jessy laptop:</div>
<div>
<ul>
<li>download the <a href="http://forum.energymicro.com/topic/990-simplicity-studio-120-energyaware-tools-osx-linux/" target="_blank">simplicity studio beta</a></li>
<li>unzip the zipfile somewhere</li>
<li>enter the studiow/ map</li>
<li>start the start-studio.sh shell script: ./start-studio.sh</li>
</ul>
<div>
This will provide you with an installer for the simplicity studio software. This installer will install all the needed software. When the software is installed you can start simplicity studio itself also with ./start-studio.sh.</div>
</div>
<div>
<br /></div>
<div>
In the simplicity studio main tool page press the <i>add-remove </i>button and use it to install everything. This will download all the examples, demos and app-notes.</div>
<div>
<br /></div>
<div>
Now while the main tool works, I quickly found out that most sub-tools didn't. It turned out that because simplicity studio is a 32-bit application and my system is 64-bit, I was missing some 32-bit libraries it needs, although I could imagine some people also missing some libraries on their 32-bit system.</div>
<div>
<br /></div>
<div>
A quick apt-get to the rescue:</div>
<div>
<br /></div>
<div>
<code>
sudo apt-get install libusb-0.1-4:i386 libqt4-svg:i386 </code></div>
<div>
<br /></div>
<div>
Depending on your system you may need to install some more missing libraries. This is rather easy to see as if you started simplicity studio from the command-line it will print out a missing library when you access a tool that is needing it.<br />
<br /></div>
<div>
<br /></div>
<h2>
Demos</h2>
<div>
The easiest way to play with the dev-kits is run some of the demos. Connect the board with the mini usb cable and press the Demos button in simplicity studio. Select a demo and press start. It will upload the demo and start the energyAware profiler program allowing you to real-time monitor the current consumption for that particular demo.<br />
<br /></div>
<div>
<br /></div>
<h2>
Compilers & Uploading</h2>
<div>
Demos are fun, but compiling your own code requires some more setup.</div>
<div>
<br /></div>
<div>
<ul>
<li>download and install the arm-gcc compiler from <a href="https://launchpad.net/gcc-arm-embedded" target="_blank">https://launchpad.net/gcc-arm-embedded</a></li>
<li>in simplicity studio press examples, select the dev-board you're using (EFM32WG_STK3800 for the wonder gecko, EFM32ZG_STK3200 for the zero gecko)</li>
<li>choose the blink example (or another one)</li>
<li>press open folder, this will open some gui explorer for your desktop environment</li>
<li>go to that directory in the shell, in my case it is /some/path/kits/EFM32WG_STK3800/examples/blink</li>
<li>enter the armgcc directory</li>
<li>there is a makefile there called Makefile.blink</li>
<li>open the file with an editor and a definition for your toolchain location to it, in my case I added</li>
</ul>
<div>
<code>
LINUXCS := /some/path/gcc-arm-embedded/gcc-arm-none-eabi-4_7-2013q3</code></div>
</div>
<div>
<br /></div>
<div>
<ul>
<li>alternatively you could just export that LINUXCS to the environment</li>
<li>now do:</li>
</ul>
<div>
<code>
make -f Makefile.blink</code></div>
<ul>
<li>it will now have made a file blink.bin in the exe/ subdirectory</li>
<li>you can upload this bin file with the tool called "energyAware commander", this should be easy</li>
<li>alternatively you can use energyAware commander to upload from the commandline:</li>
</ul>
<div>
<code>
./start-eACommander.sh --flash /some/path /kits/EFM32WG_STK3800/examples/blink/armgcc/exe/blink.bin</code>
<br />
<br />
The same principle works for other examples and app-notes.<br />
<br />
<h2>
Some more pics</h2>
</div>
</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhapHKv_amtLddLcCSMNmwDu8q9cG8K_Ilmz9Jo_iXdjPmIeAO9xSqOxRlztaJSLki23GJ0vb-Uxj9YX7TiibPeT6DxZCix02JxMp8-bSMBz7J85FJ3kxsZGySLe8nEomj5eDpWplqVym-_/s1600/sharp_memory_LCD_closeup.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhapHKv_amtLddLcCSMNmwDu8q9cG8K_Ilmz9Jo_iXdjPmIeAO9xSqOxRlztaJSLki23GJ0vb-Uxj9YX7TiibPeT6DxZCix02JxMp8-bSMBz7J85FJ3kxsZGySLe8nEomj5eDpWplqVym-_/s400/sharp_memory_LCD_closeup.JPG" height="265" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">a closeup of the 128x128 sharp memory LCD display on the ZERO GECKO</td></tr>
</tbody></table>
<div>
<br /></div>
<div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheNnwkMnruixRMH91mv97CqiFIx56nC9VK36s_LyMDZP4WYXCuT0h3sfbgDkaT0swOfPbO26hXS3xlpLLAoclNtZziLbS1B58CYlQKyEeVhbtZyHGHkLSVXech9e4giFgD_yloNxUxr_QO/s1600/clock.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheNnwkMnruixRMH91mv97CqiFIx56nC9VK36s_LyMDZP4WYXCuT0h3sfbgDkaT0swOfPbO26hXS3xlpLLAoclNtZziLbS1B58CYlQKyEeVhbtZyHGHkLSVXech9e4giFgD_yloNxUxr_QO/s400/clock.JPG" height="200" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">ZERO GECKO running an analog clock demo</td></tr>
</tbody></table>
<br /></div>
<div>
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgg9nQMTX7bmk2auUgHyyYUpL2xc7Rzf35gRJ2l_d53Oo9uUoqE8WUNEx1giCuZtLNldV7ATx2xMxRG0UzaNMDB7D4hWf-O7IE94VASUVUQGnXVUetuqV8zYw2UewnE6fdkd3uUdq4_k-xL/s1600/M0_closeup.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgg9nQMTX7bmk2auUgHyyYUpL2xc7Rzf35gRJ2l_d53Oo9uUoqE8WUNEx1giCuZtLNldV7ATx2xMxRG0UzaNMDB7D4hWf-O7IE94VASUVUQGnXVUetuqV8zYw2UewnE6fdkd3uUdq4_k-xL/s400/M0_closeup.JPG" height="317" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Cortex-M0+ closeup</td></tr>
</tbody></table>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBu4PzRwRzeyR82GcZ4nrCfMLqIZdGUdZOBDBuigTx-3Z5aaM84id0UhPrFPF0Ns4UQH0OZyaVTUpDcbgzouXIgzJmzsHzWrmkrF51VsQ18fojNmschjvCOYoMjZXV6EhLEZfnRKqH6Xy4/s1600/M4.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBu4PzRwRzeyR82GcZ4nrCfMLqIZdGUdZOBDBuigTx-3Z5aaM84id0UhPrFPF0Ns4UQH0OZyaVTUpDcbgzouXIgzJmzsHzWrmkrF51VsQ18fojNmschjvCOYoMjZXV6EhLEZfnRKqH6Xy4/s400/M4.JPG" height="265" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Cortex-M4 closeup</td></tr>
</tbody></table>
<br />
<br />Anonymoushttp://www.blogger.com/profile/09143890844136884489noreply@blogger.com0tag:blogger.com,1999:blog-8979045496387455785.post-70179298454305786452013-12-15T12:02:00.002+01:002014-03-02T15:21:05.645+01:00madparts release 1.2.1This is mostly a bug-fix release, mainly fixing bugs to do with rotation of certain parts, especially in combination with KiCAD export.<br />
<br />
Builds are available for Debian Jessie and Wheezy, Ubuntu Saucy, MacOSX and Win32.<br />
<br />
Go download one of them at <a href="http://madparts.org/footprint.html#download" target="_blank">http://madparts.org/footprint.html#download</a> !<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwjKghyPYL4kymqYCz9bOxL4S_gtTBc87VPfbdj4ZqoNSKAmgJ1EgzbqesNf-2Vlh1O-lesmJW1zpnuzzLMVRL74gJRmo68rt1PCIhV6fqm2Z4cKtguQl-Jcipx37K5G68_fj1h4aFh0yH/s1600/mp1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwjKghyPYL4kymqYCz9bOxL4S_gtTBc87VPfbdj4ZqoNSKAmgJ1EgzbqesNf-2Vlh1O-lesmJW1zpnuzzLMVRL74gJRmo68rt1PCIhV6fqm2Z4cKtguQl-Jcipx37K5G68_fj1h4aFh0yH/s640/mp1.png" height="360" width="640" /></a></div>
<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/09143890844136884489noreply@blogger.com0tag:blogger.com,1999:blog-8979045496387455785.post-59066165503857116732013-12-24T16:28:00.000+01:002014-03-02T14:56:14.220+01:00using madparts for making electronics footprints: an eleborate exampleIn this blog post I'm discussing a more complex footprint I've made and how I made it with <a href="http://madparts.org/footprint.html" target="_blank">madparts</a> based on the vendor's specification. More specifically I'm making a footprint for the Bluegiga BLE113 Bluetooth Low Energy module.<br />
<br />
Lets start by collecting all the needed data.<br />
<br />
<div>
The physical dimensions of the module are found in the spec page 16:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7vf77ffXlnNBXr5I4sFbJ5lbw920s9eT1MP1per651On7FzVQrfkFdVWOhnBFrVM2Y4qY3cy69U4NIOAyPlGAkhMF0pDYMFnHwvKhF5cPXU1SnxWCxugW4dOTOXITSlfEoMIdwAuBrQAM/s1600/phys.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7vf77ffXlnNBXr5I4sFbJ5lbw920s9eT1MP1per651On7FzVQrfkFdVWOhnBFrVM2Y4qY3cy69U4NIOAyPlGAkhMF0pDYMFnHwvKhF5cPXU1SnxWCxugW4dOTOXITSlfEoMIdwAuBrQAM/s1600/phys.png" /></a></div>
<div>
This will be used to define the physical boundaries of the package.</div>
<div>
<br /></div>
<div>
Next is the landing pattern. It can be found on page 17 of the specification:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQGjn3mPi_V7lCRluGOmpbLSziUR_BepyA83muTEdWbEbCRHPhMcG-YFogAOPpD9PguIfXKezU7uZSI9FYnzBThlfmJPjmyJuePc9Z9s5zs_eW88oBnPXn0dBbxYavAHFhUn95lOeE1EvZ/s1600/land.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQGjn3mPi_V7lCRluGOmpbLSziUR_BepyA83muTEdWbEbCRHPhMcG-YFogAOPpD9PguIfXKezU7uZSI9FYnzBThlfmJPjmyJuePc9Z9s5zs_eW88oBnPXn0dBbxYavAHFhUn95lOeE1EvZ/s1600/land.png" /></a></div>
<div>
This is used to define the pads for the module.</div>
<div>
<br /></div>
<div>
The order of the pins can be found on page 7:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpGor6IMvJaeF7S9uJ1ZhVJH3QqsdbsP361mbDSUvr_bxtw3RxXaTwYLOf3499o8VqcpyQkg-H5-EegxH9AmybpuPIAtQBw6tdGEtj_u0u7TJKHBS3g5IYcZDAQXlmnjTzo9PCzvuOQZmc/s1600/order.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpGor6IMvJaeF7S9uJ1ZhVJH3QqsdbsP361mbDSUvr_bxtw3RxXaTwYLOf3499o8VqcpyQkg-H5-EegxH9AmybpuPIAtQBw6tdGEtj_u0u7TJKHBS3g5IYcZDAQXlmnjTzo9PCzvuOQZmc/s320/order.png" height="320" width="286" /></a></div>
<div>
Finally the specification also gives a clearance for the antenna on page 20:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUgk0dqpHMMcjG9oiVqDg0W0RJAFnK7kmKM7piW10FgHjSIKFwA7yClPh8TPx4Amy_YYVtwGPaYiG_neL4TWgYXxbuwWYIK3XOVdPMRb5laRA7tX-jsLgs5TwAJZHQ6Mlbc_SLwuXpamTx/s1600/clear.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUgk0dqpHMMcjG9oiVqDg0W0RJAFnK7kmKM7piW10FgHjSIKFwA7yClPh8TPx4Amy_YYVtwGPaYiG_neL4TWgYXxbuwWYIK3XOVdPMRb5laRA7tX-jsLgs5TwAJZHQ6Mlbc_SLwuXpamTx/s320/clear.png" height="285" width="320" /></a></div>
<div>
This means we'll have to add a restrict area to the part for this clearance area.</div>
<div>
<br /></div>
<div>
let's write code!</div>
<div>
<br /></div>
<div>
Define the size of the module as found in the physical dimensions:</div>
<br />
<pre class="prettyprint"> module_dx = 9.15
module_dy = 15.74
</pre>
<br />
Define the size of the pad as found in the recommended landing pattern:
<br />
<br />
<pre class="prettyprint"> pad_dx = 2
pad_dy = 0.5
</pre>
<br />
The horizontal pads need an adjustment from the center of the module. The landing pattern defines 5.35mm between the two columns of pads, and we orient from the center of the pad so in total this gives and adjustment value of:
<br />
<br />
<pre class="prettyprint"> pad_hadj = (5.35+pad_dx)/2
</pre>
<br />
The landing pattern tells us the distance between pads:
<br />
<br />
<pre class="prettyprint"> pad_between = 0.8
</pre>
<br />
The pinout description gives the number of pins:
<br />
<br />
<pre class="prettyprint"> n_left = 18
n_down = 6
n_right = 12
</pre>
<br />
The physical dimension tells us the distance from the bottom of the module to the center of the bottom left and right pad. This works because the pad centers are the same for the physical diagram and the landing pattern.
<br />
<br />
<pre class="prettyprint"> lr_pad_from_bottom = 1.45
</pre>
<br />
Now this gets a bit tricky. We need to calculate the vertical adjustment needed for the column of pads, but this is relative to the center of the module.
The trick is to take pad 18, move it to the 0 point, then to the bottom of the module, and then use the lr_pad_to_bottom adjust value specified in the spec.
<br />
<br />
<pre class="prettyprint"> pad_vadj = ((n_left-1)/2)*pad_between # move pad 18 to 0
pad_vadj -= module_dy/2 # move pad 18 down to bottom
pad_vadj += lr_pad_from_bottom # and back up by 1.45
</pre>
<br />
Let's draw a rectangle to document the module shape, and draw a silk around it to make it easily visible on the board later.
<br />
<br />
<pre class="prettyprint"> r1 = make_rect module_dx, module_dy, 0.1, 'docu'
r2 = make_rect module_dx+0.2, module_dy+0.2, 0.1, 'silk'
</pre>
<br />
Let's define the pad shape with the earlier defined constant. we want 100% round corners.
<br />
<br />
<pre class="prettyprint"> pad = new Smd
pad.dx = pad_dx
pad.dy = pad_dy
pad.ro = 100
</pre>
<br />
Now lets make the left row of pads. First make them, then adjust the x and y by the values we calculated earlier.
<br />
<br />
<pre class="prettyprint"> l1 = single pad, n_left, pad_between
l1 = adjust_x l1, -pad_hadj
l1 = adjust_y l1 , pad_vadj
</pre>
<br />
Next the bottom row. clone and rotate the pad, and create a horizontal row of pads. Adjust the y as specified in the landing pattern figure. Finally renumber starting with the number after the last number we used for the first column of pads.
<br />
<br />
<pre class="prettyprint"> l2 = rot_single (rotate90pad clone pad), n_down, pad_between
l2 = adjust_y l2, -module_dy/2+lr_pad_from_bottom-0.55
l2 = generate_names l2, n_left
</pre>
<br />
Finally the right row. Again a single row of pads. Reverse the order. Renumber starting after the last number used for the down pads.
<br />
<br />
<pre class="prettyprint"> l3 = single pad, n_right, pad_between
l3 = reverse l3
l3 = generate_names l3, n_left+n_down
l3 = adjust_x l3, pad_hadj
l3 = adjust_y l3, pad_vadj+(n_right-n_left)/2*pad_between
</pre>
<br />
Let's add a name somewhere inside the module, a bit below the top:
<br />
<br />
<pre class="prettyprint"> name = new Name (module_dy/2-1)
</pre>
<br />
Let's add a rectangular for the restrict area. This is a but messy but it boils down to placing it right above pas 36 and 3.5mm on the right of the left side of the module.
<br />
<br />
<pre class="prettyprint"> k = new Rect
k.type = 'restrict'
k.dx = module_dx
k.dy = module_dy/2-l3[n_right-1].y
k.x = -module_dx/2+3.5+k.dx/2
k.y = l3[n_right-1].y+pad_dy/2+k.dy/2
</pre>
<br />
Finally combine it all in a list and we're done.
<br />
<br />
<pre> combine [name, r1,r2, l1, l2,l3, k]
</pre>
<br />
The latest version of the full file can be found at <a href="https://github.com/andete/madparts-parts/blob/master/3ca17b8bc41648d2b968c33ae8f35092.coffee" target="_blank">https://github.com/andete/madparts-parts/blob/master/3ca17b8bc41648d2b968c33ae8f35092.coffee</a><br />
<br />
This is a screenshot:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEis3mdiCCzzMCYe2cDEDm2e-p4ebZqZMcwwfLccEHPkc12HuO_9pdWiKPPT6QxTkSAOQsVsHCdZogrEtn8uPX96f2xUB9DtXqwxRXOQtQDDzhhPy8Se7IiV8pn1KQ5BHEDZvdGQAyPGkwU_/s1600/scr.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEis3mdiCCzzMCYe2cDEDm2e-p4ebZqZMcwwfLccEHPkc12HuO_9pdWiKPPT6QxTkSAOQsVsHCdZogrEtn8uPX96f2xUB9DtXqwxRXOQtQDDzhhPy8Se7IiV8pn1KQ5BHEDZvdGQAyPGkwU_/s320/scr.png" height="180" width="320" /></a></div>
<br />
And this is the part in eagle cad:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfvAn1fU1OoW-vflUmkvf7iBaP8kawbv74lacFYBbx83RSpNZySIWQiS19XPrFvmxByBU0FwWkR9rLOBXo5Cr4mkqMF6uyRuztifl_ZmGMkSkCLuJhyCGCzFcP4Ei180Qv6w8kdA64nv0I/s1600/eagle.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfvAn1fU1OoW-vflUmkvf7iBaP8kawbv74lacFYBbx83RSpNZySIWQiS19XPrFvmxByBU0FwWkR9rLOBXo5Cr4mkqMF6uyRuztifl_ZmGMkSkCLuJhyCGCzFcP4Ei180Qv6w8kdA64nv0I/s320/eagle.png" height="180" width="320" /></a></div>
<br />
And in kicad:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiU2kTPeAnXQuLF939TZEETg9S9NGAytXlA7YkYZEEJY8cgQbMavJM-mluWBXlVUrSi78Es6GeYsp0vL58UeZgWa4QLDbIwRjaOOwg252sqPQ0l89X30xI_q6AqryNECtGe5qYI6ZZT22M_/s1600/kicad.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiU2kTPeAnXQuLF939TZEETg9S9NGAytXlA7YkYZEEJY8cgQbMavJM-mluWBXlVUrSi78Es6GeYsp0vL58UeZgWa4QLDbIwRjaOOwg252sqPQ0l89X30xI_q6AqryNECtGe5qYI6ZZT22M_/s320/kicad.png" height="180" width="320" /></a></div>
<br />Anonymoushttp://www.blogger.com/profile/09143890844136884489noreply@blogger.com0tag:blogger.com,1999:blog-8979045496387455785.post-55373398104848787452013-12-21T11:30:00.002+01:002014-03-02T14:56:00.016+01:00a look inside the shielding can of the BLE112 Bluetooth Low Energy moduleGiven that I accidentally damaged this Bluetooth Low Energy anyway, I thought it interesting to take a look what is inside the shielding can with a macro lens.<br />
<br />
Here you see the bluegiga BLE112 module on a board with the shield still in place:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjF999PcbDb_gE1f7vr0n5d10ELVUiy-OcGQe1IFfTf0AoScaLAMBcKCPFZ-QkDhm1sYhZTgduk2ITJToAYZwODS9RQChMTju_tA6Bggwi6XRe8XvlPsgjrdS8L3DgpmGAmganmdqWJ1oLR/s1600/IMG_20131219_192810.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjF999PcbDb_gE1f7vr0n5d10ELVUiy-OcGQe1IFfTf0AoScaLAMBcKCPFZ-QkDhm1sYhZTgduk2ITJToAYZwODS9RQChMTju_tA6Bggwi6XRe8XvlPsgjrdS8L3DgpmGAmganmdqWJ1oLR/s400/IMG_20131219_192810.jpg" height="275" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
And here I removed the metal shielding can:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIQTwMOywUAzTWih1JIv-ALbVZw7YG9yTPcvdWDvXUf42Np3rY6l6e3Tio-g-Bgfz9HpwlLPWYywPMDkHOttMEJJga6HI4oL522d4nvW6prpjrq1yl-5joNKc1L5NDCc0XlhGSI8oF9rsR/s1600/ble112.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIQTwMOywUAzTWih1JIv-ALbVZw7YG9yTPcvdWDvXUf42Np3rY6l6e3Tio-g-Bgfz9HpwlLPWYywPMDkHOttMEJJga6HI4oL522d4nvW6prpjrq1yl-5joNKc1L5NDCc0XlhGSI8oF9rsR/s640/ble112.jpg" height="424" width="640" /></a></div>
<br />
As you can see no real surprises here:<br />
<br />
The central unit is a Texas Instruments CC2540 SoC Bluetooth Low Energy module.<br />
On the lower right of it sits a 32 Mhz crystal for the main clock.<br />
Above it is what I assume the 32.768 kHz low speed clock crystal.<br />
<br />
The antenna was already visible with the can in place, but what's interesting is the second companion chip inside the can. I assume it is some kind of filter for the antenna.<br />
<br />
Besides that just a few passives and that is it!Anonymoushttp://www.blogger.com/profile/09143890844136884489noreply@blogger.com0tag:blogger.com,1999:blog-8979045496387455785.post-43309072896612562552014-01-20T10:51:00.001+01:002014-03-02T14:55:44.241+01:00programming the attiny10 in linuxThe <a href="http://www.atmel.com/devices/attiny10.aspx" target="_blank">attiny10</a> (and it's brothers attiny4,5 and 9) is a cute little 6-pin SOT23-6 AVR micro-controller. The very tiny footprint and low price makes it interesting as replacement for e.g. the 555 in simple circuits.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCMdKVIzB2PQt_co7DOwSZAJHBejEZDCmlh2B2fTD_aKRFCM5T7rnr_J1hIdQYlEypR4grgU4cxmfgPUJ7Z97Q74lTe9_xsi2RrGEBZtnirIsyg6IAVcGL9hFu5h1tcoUks93VSbpxax-O/s1600/attiny10.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCMdKVIzB2PQt_co7DOwSZAJHBejEZDCmlh2B2fTD_aKRFCM5T7rnr_J1hIdQYlEypR4grgU4cxmfgPUJ7Z97Q74lTe9_xsi2RrGEBZtnirIsyg6IAVcGL9hFu5h1tcoUks93VSbpxax-O/s1600/attiny10.JPG" height="308" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">attiny10 sitting between a 5050 RGB LED and a 555 timer IC</td></tr>
</tbody></table>
<br />
<br />
Programming it seems to have been quite involved but the more recent gcc supports it just fine, making it finally easier to use. I tested with 4.8.1 <a href="http://www.atmel.com/tools/atmelavrtoolchainforlinux.aspx" target="_blank">downloaded from Atmel</a>, as the one provided by Debian (also 4.8.1) did not yet have the definitions for the attiny10. It seems like the public source tree for the avr tool lags behind quite a bit against the Atmel provided toolchain ...<br />
<br />
For programming I'm using an AVRISP-MKII. I updated it to the latest firmware. This updating unfortunately requires avrstudio in windows; programming itself works fine in Linux.. You may also need a recent avrdude. I'm using 6.0.1.<br />
<br />
Programming requires that the chip is powered by 5V according to the spec. I can confirm that this is the case because I tried it with 3.3V and it didn't work, it tries to program but fails on verification.<br />
<br />
Once programmed the chip runs all the way down to 1.8V.<br />
<br />
The pin mapping is pretty obvious:<br />
<br />
attiny10 pinout:<br />
<br />
<ol>
<li>PB0/TPIDATA</li>
<li>GND</li>
<li>PB1/TPICLK</li>
<li>PB2</li>
<li>VCC</li>
<li>PB3/RESET</li>
</ol>
<div>
AVRISP-MkII pinout:</div>
<div>
<br /></div>
<div>
<ol>
<li>MISO</li>
<li>VCC</li>
<li>SCK</li>
<li>MOSI</li>
<li>RESET</li>
<li>GND</li>
</ol>
<div>
And the mapping:</div>
</div>
<div>
<br /></div>
<div>
<ul>
<li>TPIDATA - MISO</li>
<li>TPISCK - SCK</li>
<li>RESET - RESET</li>
<li>GND - GND</li>
<li>VCC - VCC</li>
</ul>
<div>
The following C++ code blinks a LED every second on pin PB2:</div>
</div>
<pre class="prettyprint">#include <util/delay.h>
#include <avr/io.h>
static inline void setup() {
// configure PB2 pin
PUEB &= ~_BV(PUEB2); // disable Pull-Up
DDRB |= _BV(DDB2); // enable Output mode
PORTB &= ~_BV(PORTB2); // set output to Low
}
int main() {
setup();
while (true) {
PORTB &= ~_BV(PORTB2);
_delay_ms(500);
PORTB |= _BV(PORTB2);
_delay_ms(500);
}
return 0;
}
</pre>
The following makefile builds it and uploads it with the help of avrdude:
<br />
<br />
<pre class="prettyprint"># Makefile loosely derived from generated avr toolchain makefile
PROG := avrispmkii
MCU := attiny10
F_CPU := 1000000
TARGET := blink
COMMONFLAGS = -g -Os -funsigned-char -funsigned-bitfields \
-fpack-struct -fshort-enums -Wall -DF_CPU=$(F_CPU) -mmcu=$(MCU)
CFLAGS = -std=gnu99 $(COMMONFLAGS) -Wstrict-prototypes \
-Wa,-adhlns=$(<:.c=.lst) \
CXXFLAGS = -std=gnu++11 $(COMMONFLAGS) -fno-exceptions -fno-rtti \
-Wa,-adhlns=$(<:.cc=.lst) \
ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
# TODO fuses
# FUSE:=-U lfuse:w:0xff:m -U hfuse:w:0xd9:m -U efuse:w:0xff:m
AVRDUDE:=avrdude -c $(PROG) -p $(MCU)
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
TC = /your/path/to/avr8-gnu-toolchain-linux_x86_64
CC = $(TC)/bin/avr-gcc
CXX = $(TC)/bin/avr-c++
OBJCOPY = $(TC)/bin/avr-objcopy
OBJDUMP = $(TC)/bin/avr-objdump
SIZE = $(TC)/bin/avr-size
default: $(TARGET).hex
check:
$(AVRDUDE)
fuse:
$(AVRDUDE) $(FUSE)
upload:
$(AVRDUDE) $(AVRDUDE_WRITE_FLASH)
%.hex: %.elf
$(OBJCOPY) -O ihex -R .eeprom $< $@
$(SIZE) $@
.SECONDARY : $(TARGET).elf
.PRECIOUS : $(OBJ)
%.elf: %.o
$(CC) $(CFLAGS) $< --output $@ $(LDFLAGS)
%.o : %.c
$(CC) -c $(CFLAGS) $< -o $@
%.o : %.cc
$(CXX) -c $(CXXFLAGS) $< -o $@
%.s : %.c
$(CC) -S $(CFLAGS) $< -o $@
%.o : %.S
$(CC) -c $(ALL_ASFLAGS) $< -o $@
clean:
-rm *.hex
-rm *.lst
-rm *.obj
-rm *.elf
-rm *.o</pre>
In action:
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhp0ESaKx-UHk2b1ay0LP5Nhn5M14djcnZrD-X8UXcpePDtenjmaAPhmEHY0AQM0tbJx8k4BhUTpOMnZmozfN67xQlJseAs-dutzkuetDjgWo2t9UNB4G5YpLD7vp7zEfNE5ddCSOK-TgSp/s1600/IMG_20140120_095131.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhp0ESaKx-UHk2b1ay0LP5Nhn5M14djcnZrD-X8UXcpePDtenjmaAPhmEHY0AQM0tbJx8k4BhUTpOMnZmozfN67xQlJseAs-dutzkuetDjgWo2t9UNB4G5YpLD7vp7zEfNE5ddCSOK-TgSp/s1600/IMG_20140120_095131.jpg" height="320" width="240" /></a></div>
<br />Anonymoushttp://www.blogger.com/profile/09143890844136884489noreply@blogger.com0tag:blogger.com,1999:blog-8979045496387455785.post-33210135018091432292013-12-14T10:19:00.001+01:002013-12-14T10:19:58.714+01:00stm32f105 cortex-m3 getting to blinkThis is not going to be a detailed post. All the code can be found in github at <a href="https://github.com/andete/blog-stuff/tree/master/STM32F105" target="_blank">https://github.com/andete/blog-stuff/tree/master/STM32F105</a> .<br />
<br />
In my quest for more experience with different microcontrollers I made a little breakout for the ST STM32F105 ARM Cortex-M3 micro-controller.<br />
<br />
The breakout provides a 8Mhz external clock, which is multiplied by 9 by the internal PLL to give a nice 72Mhz clock.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqEXJH8Do655l7ff2Fv8AI83XDR_OUhGEjyZgHB2vI_vxGnulfhMMvAl_BPgnfHVmWebw4NVioMTQXV9lzoM5wmpBi4n8ZO8Q0piIAU-ODpMo8USVk2Ftqnab0CIn6R2H0aJmLiRQ5d_7P/s1600/board.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqEXJH8Do655l7ff2Fv8AI83XDR_OUhGEjyZgHB2vI_vxGnulfhMMvAl_BPgnfHVmWebw4NVioMTQXV9lzoM5wmpBi4n8ZO8Q0piIAU-ODpMo8USVk2Ftqnab0CIn6R2H0aJmLiRQ5d_7P/s640/board.jpg" width="640" /></a></div>
<br />
The MCU is programmed with the STLINK V2 programmer via SWD. It should also be possible to program it via DFU but I have not tried that yet.<br />
<br />
I cobbled some code together from all over the internet to make a simple blink file.<br />
<br />
<br />
<pre class="prettyprint">#include "stm32f10x.h"
// loosely based on
// http://www.overtracks.com/stm32/baby-steps.htm
// http://dics.voicecontrol.ro/dicsEE-IP/chapter/Setting%20GPIO%20manually
// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0497a/BGBEEJHC.html
// https://forum.sparkfun.com/viewtopic.php?f=11&t=21107
// http://en.radzio.dxp.pl/stm32vldiscovery/
// LED is connected to PC0, so first bit on GPIOC
#define LED_BITMASK 1 << 0 // bit 0
#define USE_SYSTICK
#ifdef USE_SYSTICK
void SysTick_Handler(void) {
GPIOC->ODR ^= LED_BITMASK; // toggle LED state
}
#else
void TIM3_IRQHandler(void) {
// why the check for UIF ?
if (TIM3->SR & TIM_SR_UIF) // if UIF flag is set
{
TIM3->SR &= ~TIM_SR_UIF; // clear UIF flag
GPIOC->ODR ^= LED_BITMASK; // toggle LED state
}
}
#endif
int main() {
// enable GPIOC
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;
// configure GPIOC port 0 as output; 4 bits per pin
// 4+0 -> (0) input mode, (4) floating (reset state)
// 0+2 -> (2) output mode, (0) generic push-pull
GPIOC->CRL = 0x44444442;
#ifdef USE_SYSTICK
// 1 second = 72000000 / 8000000 = 9000000
SysTick->LOAD = 9000000;
// start counting from zero
SysTick->VAL = 0;
// enable and enable interrupt
SysTick->CTRL |= (SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk);
#else
// enable clock for timer3
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
// Set prescaler to 24 000 (PSC + 1) // why?
TIM3->PSC = 23999;
// // Auto reload value 1000
TIM3->ARR = 1000;
// Enable update interrupt (timer level)
TIM3->DIER = TIM_DIER_UIE; // Enable update interrupt (timer level)
TIM3->CR1 = TIM_CR1_CEN; // Enable timer
NVIC_EnableIRQ(TIM3_IRQn);
#endif
// sleep till the end of time
while (1) { __WFI(); }
return 0;
}
</pre>
It does blinking via the SysTick interrupt or alternatively via the TIM3 timer interrupt.
It is also possible to do this without interrupts at all, just using the timers, but this is not shown here.
Anonymoushttp://www.blogger.com/profile/09143890844136884489noreply@blogger.com0tag:blogger.com,1999:blog-8979045496387455785.post-74355291377735828642013-08-19T21:03:00.000+02:002013-08-19T21:06:18.230+02:00madparts release 1.2It's been a few months, but finally the <a href="http://madparts.org/" target="_blank">new madparts 1.2</a> release is available!<br />
<br />
Madparts is a functional electronics footprint editor with support for the Kicad and Eagle electronics Cad programs.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggRxGvieMXPGbC2WlY6Ei5m5LU5AMH6j6M0f4nss6iW1ujK2D39j8uc5MTNdYcVnVYv0kM7-BwX-2px15_nwM_ADllSwVa_uaor7IdF15aihC-6pk08IKJ6xfBJZJ0h279Ihxyqkm0jO_L/s1600/screenshot.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggRxGvieMXPGbC2WlY6Ei5m5LU5AMH6j6M0f4nss6iW1ujK2D39j8uc5MTNdYcVnVYv0kM7-BwX-2px15_nwM_ADllSwVa_uaor7IdF15aihC-6pk08IKJ6xfBJZJ0h279Ihxyqkm0jO_L/s320/screenshot.png" width="289" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">screenshot of madparts 1.2 running on linux/xmonad</td></tr>
</tbody></table>
<br />
<h2>
Highlights</h2>
<div>
<br /></div>
<h3>
KiCad support</h3>
<div>
<br /></div>
<div>
Finally full support for importing and exporting footprints from/to KiCad is now available. <b>madparts</b> supports both the old .mod file format and the newer .pretty/.kicad_mod file format.</div>
<div>
<br /></div>
<h3>
More shapes</h3>
<div>
<br /></div>
<div>
1.2 adds support for arcs, partial circles, polygons and holes.</div>
<div>
<br /></div>
<h3>
QtScriptEngine</h3>
<div>
<br /></div>
<div>
<a href="https://twitter.com/Rednaxander" target="_blank">Alex Schultz</a> contributed javascript handling with QtScriptEngine instead of PyV8. This means there is one less dependency for the program making it easier to install, package and maintain. It is also faster! Thanks again Alex!</div>
<div>
<br /></div>
<h3>
More documentation</h3>
<div>
<br /></div>
<div>
<a href="https://github.com/andete/madparts/wiki/Documentation" target="_blank">Documentation</a> is still sparse, but there is some more description of the supported features and code structures. Be sure to also have a look at <a href="https://github.com/andete/madparts-parts" target="_blank">my own private github repo of madparts footprints</a> for more code examples.</div>
<h2>
</h2>
<h2>
Conclusion</h2>
<div>
If you want to give it a try, head to the website at <a href="http://madparts.org/" target="_blank">http://madparts.org/</a> for more information and downloads. If you find issues or have questions, don't hesitate to email me.</div>
<div>
<br /></div>
<div>
</div>
<h2>
The future</h2>
<div>
For madparts 1.3 a few changes are planned:</div>
<div>
<ul>
<li>switch to SVG based graphics rendering to get rid of the dependency on modern openGL 2.1, making the program also usable on older computers</li>
<li>more documentation</li>
<li>better error handling</li>
</ul>
</div>
Anonymoushttp://www.blogger.com/profile/09143890844136884489noreply@blogger.com3tag:blogger.com,1999:blog-8979045496387455785.post-72542566647231102022013-08-10T14:46:00.000+02:002013-08-10T14:46:04.829+02:00using the atxmega32e5 under linuxThe Atmel AVR atxmega*e5 is an interesting chip. However it is still rather new so getting it to work on my linux environment took some tinkering.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjod5HGBgsnXxxiJubse_zTN8YD0Rudgca7liHp9F7wsLsJ1bngditBk7b8EIQrprp5ZuYAwDwwYqqj8DCnT5cSeSy1CtkRh3Y2tIiUHDAhopj4CtdavbriXWSzPcpk0hbTLe7vXSCne91b/s1600/full_board.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="268" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjod5HGBgsnXxxiJubse_zTN8YD0Rudgca7liHp9F7wsLsJ1bngditBk7b8EIQrprp5ZuYAwDwwYqqj8DCnT5cSeSy1CtkRh3Y2tIiUHDAhopj4CtdavbriXWSzPcpk0hbTLe7vXSCne91b/s640/full_board.JPG" width="640" /></a></div>
<br />
<h3>
compiler</h3>
<div>
<br />
Compiling requires a compiler that knows the CPU. In the previous post I just cheated and used a mostly compatible CPU.</div>
<div>
<br /></div>
<div>
My Debian comes default with gcc 4.7.3 which does not support the new atxmega*e5 CPU's yet. Luckily someone already packaged the gcc 4.8.1 compiler source, so it was just a matter of recompiling Debian's gcc-avr package against the gcc 4.8.1 source package. If you don't feel like that using the atxmega*D4 as cpu type during compilation is doable.<br />
<br /></div>
<h3>
avr-libc</h3>
<div>
<br />
Besides the compiler, avr-libc also needs to be adapted. It is avr-libc that provides the io description headers for the CPU's. There is no avr-libc for linux yet that does this. Luckily Atmel's AVR Studio product also uses gcc internally, and they already support the atxmega*e5 CPU's.</div>
<div>
<br /></div>
<div>
I took the files iox8e5.h, iox16e5.h and iox32e5.h from avr studio and copied these to /usr/lib/avr/include/avr/ .</div>
<div>
<br /></div>
<div>
Also /usr/lib/avr/include/avr/io.h needs to be updated to add the new CPU's:</div>
<div>
<br /></div>
<pre class="prettyprint">--- io.h.old 2013-08-10 09:51:40.963241968 +0200
+++ io.h 2013-08-10 13:29:12.682545107 +0200
@@ -382,12 +382,6 @@
# include <avr/iox32a4.h>
#elif defined (__AVR_ATxmega32D4__)
# include <avr/iox32d4.h>
+#elif defined (__AVR_ATxmega8E5__)
+# include <avr/iox8e5.h>
+#elif defined (__AVR_ATxmega16E5__)
+# include <avr/iox16e5.h>
+#elif defined (__AVR_ATxmega32E5__)
+# include <pavr/iox32e5.h>
#elif defined (__AVR_ATxmega64A1__)
# include <avr/iox64a1.h>
#elif defined (__AVR_ATxmega64A1U__)
</pre>
<div>
<br /></div>
Besides that, some other files are needed. I took the files crtx8e5.o, crtx16e5.o and crtx32e5.o from avr studio and copied these to /usr/lib/avr/lib/avrxmega2/<br />
<br />
With those two in place, compilation works :)<br />
<br />
<h3>
Example</h3>
<div>
<br /></div>
Here is an example that demonstrates the following:
<br />
<br />
<ul>
<li>switch to the internal 32Mhz oscillator</li>
<li>configure an USART on ports D6 and D7 at 9600 baud and run a simple echo follower</li>
<li>blink a LED on port A0</li>
</ul>
<br />
<br />
<pre class="prettyprint">// (c) 2013 Joost Yervante Damad <joost@damad.be>
// License: GPL3
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
static void usart_write(uint8_t data)
{
USARTD0.DATA = data;
if(!(USARTD0.STATUS & USART_DREIF_bm)) {
while(!(USARTD0.STATUS & USART_TXCIF_bm)); // wait for TX complete
}
USARTD0.STATUS |= USART_TXCIF_bm; // clear TX interrupt flag
}
static inline void init_oscillator() {
// enable 32Mhz internal oscillator
OSC.CTRL |= OSC_RC32MEN_bm;
// wait for it to be stable
while (!(OSC.STATUS & OSC_RC32MRDY_bm));
// tell the processor we want to change a protected register
CCP=CCP_IOREG_gc;
// and start using the 32Mhz oscillator
CLK.CTRL=CLK_SCLKSEL_RC32M_gc;
// disable the default 2Mhz oscillator
OSC.CTRL&=(~OSC_RC2MEN_bm);
// enable 32kHz calibrated internal oscillator
OSC.CTRL|= OSC_RC32KEN_bm;
while (!(OSC.STATUS & OSC_RC32KRDY_bm));
// set bit to 0 to indicate we use the internal 32kHz
// callibrated oscillator as auto-calibration source
// for our 32Mhz oscillator
OSC.DFLLCTRL = OSC_RC32MCREF_RC32K_gc;
// enable auto-calibration for the 32Mhz oscillator
DFLLRC32M.CTRL |= DFLL_ENABLE_bm;
}
static inline void init_usart() {
// enable clock out on port PC7
PORTCFG.CLKOUT = (PORTCFG.CLKOUT & ~PORTCFG_CLKOUTSEL_gm) | PORTCFG_CLKOUT_PC7_gc;
// set PC7 as output
PORTC.DIRSET = PIN7_bm;
// set PD7 as output for TX0
PORTD.DIRSET = PIN7_bm;
PORTD.OUTSET = PIN7_bm;
// remap USARTD0 to PD[7-4]
PORTD.REMAP |= PORT_USART0_bm;
// set baud rate 9600: BSEL=12, BSCALE=4
// as found in table in
// Atmel-42005-8-and-16-bit-AVR-Microcontrollers-XMEGA-E_Manual.pdf
USARTD0.BAUDCTRLA = 12; // BSEL
USARTD0.BAUDCTRLB = 4 << USART_BSCALE_gp; // BSCALE
// disable 2X
USARTD0.CTRLB = USARTD0.CTRLB & ~USART_CLK2X_bm;
// enable RX and TX
USARTD0.CTRLB = USARTD0.CTRLB | USART_RXEN_bm | USART_TXEN_bm;
// enable async UART 8N1
USARTD0.CTRLC = USART_CMODE_ASYNCHRONOUS_gc | USART_PMODE_DISABLED_gc | USART_CHSIZE_8BIT_gc;
USARTD0.CTRLC &= ~USART_SBMODE_bm;
USARTD0.CTRLD = 0; // No LUT
// set interrupt level for RX
USARTD0.CTRLA = (USARTD0.CTRLA & ~USART_RXCINTLVL_gm) | USART_RXCINTLVL_LO_gc;
}
static inline void init_interrupts() {
// Enable PMIC interrupt level low
PMIC.CTRL |= PMIC_LOLVLEX_bm;
// enable interrupts
sei();
}
static volatile uint8_t echo_char = 42;
int main( void )
{
init_oscillator();
// enable clock out on port PC7
PORTCFG.CLKOUT = (PORTCFG.CLKOUT & ~PORTCFG_CLKOUTSEL_gm) | PORTCFG_CLKOUT_PC7_gc;
// set PC7 as output
PORTC.DIRSET = PIN7_bm;
init_usart();
init_interrupts();
// set PA0 as output
PORTA.DIRSET = PIN0_bm;
// blink LED on PA0 with 1 second on, 1 second off
// write echo_char on USART on D7; defaults to 42(*)
while (1) {
usart_write(echo_char);
PORTA.OUTSET = PIN0_bm;
_delay_ms( 1000 );
usart_write(echo_char);
PORTA.OUTCLR = PIN0_bm;
_delay_ms( 1000 );
}
}
// USART RX receive interrupt handler
ISR(USARTD0_RXC_vect) {
echo_char = USARTD0.DATA;
}
</pre>
<br />
<h3>
Code</h3>
<div>
<br />
The code can be found on <a href="https://github.com/andete/blog-stuff/tree/master/ATXMEGAE" target="_blank">github</a>, together with the files mentioned here for convenience.<br />
<br />
<h3>
Hardware</h3>
</div>
<div>
<span style="font-size: large;"><br /></span></div>
<div>
<span style="font-size: large;">I have some extra atxmega32e5 breakout boards available. You can find them in <a href="https://www.tindie.com/products/andete/atxmega32e5-breakout-board/" target="_blank">my tindie store</a>.</span></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEip8-tme5equM8zZVOj5PS2xbVwlt_bAefVe-d1MHTKoOea-TiYz4_PjidSU8L51Is-eSpRD1A1FkpNx8RUmrcQI-wYxHzx9BCvL3rLtnjafWehRIdo6LGFEJfDk3pSTWA5OsD87AOLjEls/s1600/withftdi.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEip8-tme5equM8zZVOj5PS2xbVwlt_bAefVe-d1MHTKoOea-TiYz4_PjidSU8L51Is-eSpRD1A1FkpNx8RUmrcQI-wYxHzx9BCvL3rLtnjafWehRIdo6LGFEJfDk3pSTWA5OsD87AOLjEls/s640/withftdi.JPG" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">breakout on a breadboard with USB-serial adapter</td></tr>
</tbody></table>
<div>
<br /></div>
<div>
In addition, the eagle schematic and board files are available on github as well.</div>
<div>
<br /></div>
<h3>
More fun</h3>
<div>
<br /></div>
<div>
I'm still exploring this nice little microcontroller. Be sure to check back later on my blog for new adventures!</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
Anonymoushttp://www.blogger.com/profile/09143890844136884489noreply@blogger.com0tag:blogger.com,1999:blog-8979045496387455785.post-79002224626378400232013-08-07T09:08:00.000+02:002013-08-07T09:08:26.465+02:00atxmega enable internal 32Mhz oscillator (part 2)The atxmega also supports using the calibrated internal 32kHz clock as auto-calibration reference for the 32Mhz internal oscillator, improving the accuracy.<br />
<br />
This code should do the trick. I'm not sure how I could actually verify it. Perhaps I can get the clock signal external and get it on a scope.<br />
<br />
<br />
<pre class="prettyprint">
#include <avr/io.h>
#include <util/delay.h>
int main( void )
{
// enable 32Mhz internal oscillator
OSC.CTRL|=OSC_RC32MEN_bm;
// wait for it to be stable
while (!(OSC.STATUS & OSC_RC32MRDY_bm));
// tell the processor we want to change a protected register
CCP=CCP_IOREG_gc;
// and start using the 32Mhz oscillator
CLK.CTRL=CLK_SCLKSEL_RC32M_gc;
// disable the default 2Mhz oscillator
OSC.CTRL&=(~OSC_RC2MEN_bm);
// enable 32kHz calibrated internal oscillator
OSC.CTRL|= OSC_RC32KEN_bm;
while (!(OSC.STATUS & OSC_RC32KRDY_bm));
// set bit to 0 to indicate we use the internal 32kHz
// callibrated oscillator as auto-calibration source
// for our 32Mhz oscillator
OSC.DFLLCTRL &= ~OSC_RC32MCREF_bm;
// enable auto-calibration for the 32Mhz oscillator
DFLLRC32M.CTRL |= DFLL_ENABLE_bm;
// set PA0 as output
PORTA.DIRSET = 0b00000001;
// blink LED on PA0 with 1 second on, 1 second off
while (1) {
PORTA.OUTSET = 0b00000001 ;
_delay_ms( 1000 );
PORTA.OUTCLR = 0b00000001 ;
_delay_ms( 1000 );
}
}
</pre>Anonymoushttp://www.blogger.com/profile/09143890844136884489noreply@blogger.com0tag:blogger.com,1999:blog-8979045496387455785.post-29303157197927423452013-08-06T21:42:00.001+02:002013-08-06T21:42:56.053+02:00atxmega enable 32Mhz internal oscillatorThe atxmega (I'm playing with an atxmega16e5) has multiple internal oscillators. By default it starts on the 2Mhz clock, which is actually an 8Mhz internal oscillator divided by 4. The following code switches to the 32Mhz internal oscillator.
<br />
<br />
register definitions can be found in iox16e5.h. As I'm using an older avr-gcc I've looked in iox16d4.h instead, assuming that the base registers like for the clock are the same.<br />
<br />
<pre class="prettyprint">#include <avr io.h>
#include <util delay.h>
int main( void )
{
// enable 32Mhz internal oscillator
OSC.CTRL|=OSC_RC32MEN_bm;
// wait for the oscillator to stabilize
while (!(OSC.STATUS & OSC_RC32MRDY_bm));
// tell the processor we want to change a protected register
CCP=CCP_IOREG_gc;
// and start using the 32Mhz oscillator
CLK.CTRL=CLK_SCLKSEL_RC32M_gc;
// finally disable the default 2Mhz oscillator (optional)
OSC.CTRL&=(~OSC_RC2MEN_bm);
// set PA0 as output
PORTA.DIRSET = 0b00000001;
// blink LED on PA0 with 1 second on, 1 second off
while (1) {
PORTA.OUTSET = 0b00000001 ;
_delay_ms( 1000 )
PORTA.OUTCLR = 0b00000001 ;
_delay_ms( 1000 )
}
}
</pre>
Anonymoushttp://www.blogger.com/profile/09143890844136884489noreply@blogger.com0tag:blogger.com,1999:blog-8979045496387455785.post-68441683387413269722013-07-30T10:11:00.000+02:002013-07-30T13:38:32.979+02:00adding a new device to avrdudeSo I made a little breakout for the new Atmel AtXmega E5 series. More specifically I'm testing it with the atxmega16e5.<br />
<br />
This is a new chip that is not yet supported by the latest avrdude.<br />
<br />
Making it work turned out to be reasonably straightforward.<br />
<br />
First let's open avrdude.conf, the config file of avrdude.<br />
Let's find a section of a chip that is reasonably similar, I've selected the atxmega16d4:<br />
<br />
<pre>#------------------------------------------------------------
# ATxmega16D4
#------------------------------------------------------------
part parent ".xmegasmall"
id = "x16d4";
desc = "ATxmega16D4";
signature = 0x1e 0x94 0x42;
has_jtag = no;
memory "eeprom"
size = 0x0400;
offset = 0x08c0000;
page_size = 0x20;
readsize = 0x100;
;
memory "application"
size = 0x00004000;
offset = 0x0800000;
page_size = 0x100;
readsize = 0x100;
;
memory "apptable"
size = 0x00001000;
offset = 0x00803000;
page_size = 0x100;
readsize = 0x100;
;
memory "boot"
size = 0x00001000;
offset = 0x00804000;
page_size = 0x100;
readsize = 0x100;
;
memory "flash"
size = 0x00005000;
offset = 0x0800000;
page_size = 0x100;
readsize = 0x100;
;
;
</pre>
<br />
copy this to a new section and change the id to x16e5 and the desc to ATxmega16E5.<br />
<div>
Find the signature like by hooking up the PDI to your x16e5 board and doing:</div>
<div>
<br /></div>
<div>
avrdude -P usb -c avrispmkII -p x16d4</div>
<div>
<br /></div>
<div>
It will now say that it is the wrong signature and will print you the signature it actually found:</div>
<div>
<br /></div>
<div>
0x1e 0x94 0x45</div>
<div>
<br /></div>
<div>
Use that in the config section.</div>
<div>
<br /></div>
<div>
Now find the XML files distributed as part of Atmel AVR Studio that contain the device descriptions of the two devices: ATxmega16D4.xml and ATxmega16E5.xml</div>
<div>
<br /></div>
<div>
Now look at the differences and make the necc. changes. The only changes I made are the eeprom size, the page_size and readsize settings. The x16e5 uses 128 byte pages and the x16d4 256 byte pages.</div>
<div>
<br /></div>
<div>
This gives as a result:</div>
<div>
<br /></div>
<div>
<br /></div>
<pre>#------------------------------------------------------------
# ATxmega16E5
#------------------------------------------------------------
part parent ".xmegasmall"
id = "x16e5";
desc = "ATxmega16E5";
signature = 0x1e 0x94 0x45;
has_jtag = no;
memory "eeprom"
size = 0x0200; # J
offset = 0x08c0000;
page_size = 0x20;
readsize = 0x80; # J was 0x100
;
memory "application"
size = 0x00004000;
offset = 0x0800000;
page_size = 0x80;
readsize = 0x80;
;
memory "apptable"
size = 0x00001000;
offset = 0x00803000;
page_size = 0x80;
readsize = 0x80;
;
memory "boot"
size = 0x00001000;
offset = 0x00804000;
page_size = 0x80;
readsize = 0x80;
;
memory "flash"
size = 0x00005000;
offset = 0x0800000;
page_size = 0x80;
readsize = 0x80;
;
;
</pre>
<div>
</div>
<div>
<br />
This seems to work fine for programming. I'm pretty sure some things are still missing concerning fuses and such though.<br />
<br />
In order to get code compiled with gcc I use another atxmega target as chip as the x16e5 is not yet part of<br />
the avr-gcc I'm using either.<br />
<br />
./avrdude -C ./avrdude.conf -e -P usb -c avrispmkII -p x16e5 -U flash:w:blink.hex<br />
<br />
And it blinks :)</div>
Anonymoushttp://www.blogger.com/profile/09143890844136884489noreply@blogger.com0tag:blogger.com,1999:blog-8979045496387455785.post-49910743438727984332013-05-14T09:14:00.002+02:002013-07-23T11:30:03.623+02:00high power LED retrofit (part 4)So the lamp is working fine. Here it is suspended to the stairs for duration testing.<br />
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjA3-XxMyKxZOofDKqFd4x8HU5CQHhfH4KyeVmTxwWLVy67MjyeG8wKBGSU4aYevh5q2Y0iSET9ARUTj35UN6H5ISEPvPMDaKNLU610IZNfnIoVFNnMcfxhSZgZg5lBTEL5jcJUbbWEUtpM/s1600/IMG_20130509_122644.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjA3-XxMyKxZOofDKqFd4x8HU5CQHhfH4KyeVmTxwWLVy67MjyeG8wKBGSU4aYevh5q2Y0iSET9ARUTj35UN6H5ISEPvPMDaKNLU610IZNfnIoVFNnMcfxhSZgZg5lBTEL5jcJUbbWEUtpM/s640/IMG_20130509_122644.jpg" width="478" /></a></div>
<div>
<br /></div>
<div>
So dimming works, remote control works and temperature measurement all works. For some reason Lux measurement is not working, I think I may have fried that sensor by accident.</div>
<div>
<br /></div>
<div>
Cabling is still somewhat of a mess, but I was thinking of sorting that out when the lamp is moved to it's final place.</div>
<div>
<br /></div>
<div>
Then a day passed, and I got some time to think :)</div>
<div>
<br /></div>
<div>
Right now there are two locations where active circuitry is located: near the lamp for temperature measurement and fan control, and near the power supply for on/off (relay), wireless, dimming and lux measurement.</div>
<div>
<br /></div>
<div>
These two locations are connected via a whole bunch of cables. And I'm already doing cheap wireless at one point. That is just silly!</div>
<div>
<br /></div>
<div>
So the next step will be creating a separate board with wireless for each of those two locations. The only wiring remaining between the two locations will be a 12V/GND cable, and of course the LED current cable.</div>
<div>
<br /></div>
<div>
To be continued, but somewhat further in the future as I'm working on some other things at the moment, and I want to design some proper PCBs for the next step that fit in a nice casing and such.</div>
<div>
<br /></div>
<div>
read on at <a href="http://joost.damad.be/2013/07/high-power-led-retrofit-part-5.html" target="_blank">http://joost.damad.be/2013/07/high-power-led-retrofit-part-5.html</a> !</div>
Anonymoushttp://www.blogger.com/profile/09143890844136884489noreply@blogger.com0tag:blogger.com,1999:blog-8979045496387455785.post-61108852687756473512013-07-23T11:17:00.000+02:002013-07-23T11:17:54.796+02:00high power LED retrofit (part 5)So it's been a while since I showed progress on my LED retrofit project. I've been mostly busy preparing the <a href="http://madparts.org/" target="_blank">madparts</a> 1.2 release, which should happen "real soon now".<br />
<br />
<h2>
PCBs</h2>
<div>
As discussed in the previous post, while I had everything working for one lamp, it was a total mess of cables and really not acceptable to be a permanent part of the home. Also I wanted to decouple the functionality in two parts:</div>
<div>
<ol>
<li>LED PWM, relay control and Lux sensing</li>
<li>fan PWM and temperature measurement</li>
</ol>
<div>
Main reason being that fan PWM and temperature measurement need to be done relatively close to the actual lamp, while the others should be done close to the LED driver.</div>
</div>
<div>
<br /></div>
<div>
To avoid having to run cables between the two boards, and because I'm using RF already anyway, I decided to let both boards talk directly over wireless.</div>
<div>
<br /></div>
<h3>
Schematics & board design</h3>
<div>
<br />
I'm hoping to switch to KiCAD soon, but these boards were still designed with Eagle CAD.<br />
<br /></div>
<h4>
LED PWM, relay control and Lux sensing</h4>
<div>
Overal schematic:</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;">
<img border="0" src="http://damad.be/joost/attic/blog/LED_PWM_scaled.png" width="1024" /></div>
<br />
Let's look at the different sections in detail:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiF8cDcRL8P0vDgd_yl2sPBUQ6jX95h7FR9gULW3MJegx67EqI2o18D-cQAU4Qx1jS9FKnzGg6DyCWc99Ji0D4j4yajHCm6zF-RE27QS-WzPXU-0f_vOJ_hmJrADkritp0J_LTF9LfgRrBR/s1600/LED_PWM_12V.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="326" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiF8cDcRL8P0vDgd_yl2sPBUQ6jX95h7FR9gULW3MJegx67EqI2o18D-cQAU4Qx1jS9FKnzGg6DyCWc99Ji0D4j4yajHCm6zF-RE27QS-WzPXU-0f_vOJ_hmJrADkritp0J_LTF9LfgRrBR/s400/LED_PWM_12V.png" width="400" /></a></div>
<br />
12V is taken in with a standard power connector. Diode D3 is used to protect against reverse polarity. F1 is a re-settable polyfuse, which combined with the TVS diode D4 provides further overloading protection.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCBxUk_dNq3enmbVyys_aPOKo_tFM3PucspYhQ_fRMlIHbkiSH-IJEZE0P0qwXETlUrWTLQvx6XY5G8pBFjMlLtmGZeQnB4JoJuHAwQ3r6YoOOe8y-FHXNIMvCxr3XDZdPjSSsw_80wJne/s1600/LED_PWM_5V_3V3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="170" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCBxUk_dNq3enmbVyys_aPOKo_tFM3PucspYhQ_fRMlIHbkiSH-IJEZE0P0qwXETlUrWTLQvx6XY5G8pBFjMlLtmGZeQnB4JoJuHAwQ3r6YoOOe8y-FHXNIMvCxr3XDZdPjSSsw_80wJne/s400/LED_PWM_5V_3V3.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
The 12V rail is converted to a 5V and 3.3V rail by means of MCP1703 voltage regulators.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZUDWJCZac9rononhowXgBVbGDcSL01vt6unO1tlQGZkid0EnnH0b7UlN0sn7MvMEImKyfKGW_fQQ5ERQ3nDX0CIPnqXMxIn3Os6MiSniQaX58CnPvbfsm-XEiQNztYXlZYbUR3GO2FRLI/s1600/LED_PWM_INTER.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZUDWJCZac9rononhowXgBVbGDcSL01vt6unO1tlQGZkid0EnnH0b7UlN0sn7MvMEImKyfKGW_fQQ5ERQ3nDX0CIPnqXMxIn3Os6MiSniQaX58CnPvbfsm-XEiQNztYXlZYbUR3GO2FRLI/s320/LED_PWM_INTER.png" width="267" /></a></div>
<br />
Headers are provided for Debug TX/RX serial interface, I2C bus for the Lux sensor and the standard 6-pin ISP programming header.<br />
<br />
The I2C bus is actually connected to 5V, but the Lux sensor I'm using runs on 3.3V only. (It dies on 5V :( ) This means I had to do some bodge wiring to get 3.3V instead of 5V on that connector.<br />
<br />
The Lux sensor is only connected to one of the two boards I've created because they'll be together anyway.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgk3bdEc_znDY4NalTo_Il9gGlUnuoJn1MLvlXoGnGPdsGlYBaN9_Bf8Whqluod9MqjSst3RSq2mXjwpcrIpO60dQVuUsPZDOq7ZgnDeqmtSS7w4YBVlJbC8AodZTfjGhSR29XSoKoG4wrw/s1600/LED_PWM_main.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="488" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgk3bdEc_znDY4NalTo_Il9gGlUnuoJn1MLvlXoGnGPdsGlYBaN9_Bf8Whqluod9MqjSst3RSq2mXjwpcrIpO60dQVuUsPZDOq7ZgnDeqmtSS7w4YBVlJbC8AodZTfjGhSR29XSoKoG4wrw/s640/LED_PWM_main.png" width="640" /></a></div>
<br />
The main workhorse is an Atnel AVR atmega328p microcontroller clocked at 16Mhz. A conservative choice but it allowed me to spent minimal time making the firmware as it is fully Arduino compatible. I also broke out the other pins just to be sure but I did not end up using those.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLx3UrT05DDUiOBDWBiBv6VwJXMm00P9MNsxUybRiBVrSHL6HJl7PKcFAc5BEfinK5k0SN9XljLx_3XroRgcoKX3GV9sxWAzJFjknECasAaKrD3ytSI_fMGQR6e_f0wKdPRQxOP6zizGvH/s1600/LED_PWM_RF.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="248" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLx3UrT05DDUiOBDWBiBv6VwJXMm00P9MNsxUybRiBVrSHL6HJl7PKcFAc5BEfinK5k0SN9XljLx_3XroRgcoKX3GV9sxWAzJFjknECasAaKrD3ytSI_fMGQR6e_f0wKdPRQxOP6zizGvH/s640/LED_PWM_RF.png" width="640" /></a></div>
The wireless connection is provided by a cheap RFM12B module. It is connected to the SPI bus of the main processor. This module runs on 3.3V hence the simple voltage divider action for MOSI, SCK and SS signals that go from the processor to the RFM12B. The other way around nothing is needed as 3.3V is still above the high-threshold for the processor.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjOXVBrDHmxxlN8Ho7mu6CdNdXmzhbZXlEtM2UBqFKr9edM9_PYRRQBhRCkogiARTvPj1lGJBMXhayRkiWZgzgmSCZMK_NQG9khetMWwUVT0SPNDknFuDK2Tg3ESduRwuoSuQEw2X5e8wA/s1600/LED_PWM_relay.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjOXVBrDHmxxlN8Ho7mu6CdNdXmzhbZXlEtM2UBqFKr9edM9_PYRRQBhRCkogiARTvPj1lGJBMXhayRkiWZgzgmSCZMK_NQG9khetMWwUVT0SPNDknFuDK2Tg3ESduRwuoSuQEw2X5e8wA/s640/LED_PWM_relay.png" width="620" /></a></div>
<br />
The relay used is a neat little latching relay to avoid constantly powering the relay when the lamp is on. The relay is driven from the micro-controller via the NPN transistors T1 and T2 and flyback protection diodes D1 and D2 are provided around the relay coils to absorb possible inductive kicks.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjf6oZDtSsqaAJKm5BwDZ3ysEESC-XqrOXNrly-d9ALalDS46qoijL9TCG2cM5qHf_cqM6MOPwEFnog_QTd-_S3Qk1TKXzEZY6XfxfHmoFuAH715wVJrpzYK6tcc-yKW84rOdVUPmhSSpX8/s1600/LED_PWM_conv.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="396" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjf6oZDtSsqaAJKm5BwDZ3ysEESC-XqrOXNrly-d9ALalDS46qoijL9TCG2cM5qHf_cqM6MOPwEFnog_QTd-_S3Qk1TKXzEZY6XfxfHmoFuAH715wVJrpzYK6tcc-yKW84rOdVUPmhSSpX8/s640/LED_PWM_conv.png" width="640" /></a></div>
<br />
<br />
Finally an adjustable voltage regulator together with a trim pot is used to set the peak voltage of the PWM signal towards the LED driver. This can be used to limit the maximum current provided by the LED driver. This works because internally the LED driver just converts the PWM signal to a voltage anyway with a low-pass filter. This adds another safety mechanism to limit the LED current if your setup is not capable of dissipating all the heat the LED die produces when it is running at it's maximum current rating.<br />
<br />
The PWM signal provided by the micro-controller is then first inverted an then brought up to almost the voltage level provided by the voltage regulator. In practice a small drop is still seen causing a 10V maximum output signal when the voltage regulator is set to 10.5V.<br />
<br />
R12 ensures that the LED drops to 10% dimming instead of going full on if for some reason the board dies and the lamp is still on as the LED driver also supports programming the current with a resistor.<br />
<br />
Finally this gives rise to the following board layout:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzVJvQFmeh9svWNJGwFJh85yrjOowIbeogXBWqHh9KXixatofuTCua82YO3LnOMPcnJ9jzqXx77ayHLwameU_ADi4-lJfcYErIxYGn-VQUTZlcq9AyCBiXc9dAO07PDAMy5QxmrVrsq2Wn/s1600/LED_PWM_brd.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="294" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzVJvQFmeh9svWNJGwFJh85yrjOowIbeogXBWqHh9KXixatofuTCua82YO3LnOMPcnJ9jzqXx77ayHLwameU_ADi4-lJfcYErIxYGn-VQUTZlcq9AyCBiXc9dAO07PDAMy5QxmrVrsq2Wn/s640/LED_PWM_brd.png" width="640" /></a></div>
<br />
The code has also been rewritten. I will not further explain the code.<br />
You can find code and eagle schematic and board files at <a href="https://github.com/andete/blog-stuff/tree/master/HPLEDRF2/relay_pwm" target="_blank">https://github.com/andete/blog-stuff/tree/master/HPLEDRF2/relay_pwm</a> .<br />
<br />
Note that I mirrored the power connector. Luckily I could just cut off the side pin and it still works fine.<br />
<br />
<h4>
Fan PWM and temperature sensing</h4>
<div>
<br /></div>
<div>
Overal schematic:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbQopwsI5MSQbqCYtUOSLsclzOhtQV3JRvXaRn0FVxw_ayq7ZOtWfppW9JBZniM9WOCwos25VcMFtxZf1dJm8NTDxG0Qlrt_VClSnFQwnSI1_nOxCUrWxaDDgU3xeP_uQ4fpHUrhYcIuhX/s1600/fan_temp.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="314" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbQopwsI5MSQbqCYtUOSLsclzOhtQV3JRvXaRn0FVxw_ayq7ZOtWfppW9JBZniM9WOCwos25VcMFtxZf1dJm8NTDxG0Qlrt_VClSnFQwnSI1_nOxCUrWxaDDgU3xeP_uQ4fpHUrhYcIuhX/s640/fan_temp.png" width="640" /></a></div>
<div>
<br /></div>
Many parts are the same as the other board and I will not go in them again. These are different:<br />
<br />
The fan PWM is just directly driven from the micro-controller as the FAN has 5V PWM compatible. The fan also provides a pulse signal which is connected to the INT1 interrupt pin of hte micro-controller.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaN3xrbGwQVsztOKmBdr9AqXyyv8LMst_Cg51e1uEwrdy8zw7ln8X_Jh6i31NnuPGfaC-vI0PG_dyukbOVM_VLD5KoJPgNOpbVz8iaTFs5oPSOSIXWBk5rJNuiNH9YU4gwbPH9GALcuL9U/s1600/fan_temp_adc.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="196" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaN3xrbGwQVsztOKmBdr9AqXyyv8LMst_Cg51e1uEwrdy8zw7ln8X_Jh6i31NnuPGfaC-vI0PG_dyukbOVM_VLD5KoJPgNOpbVz8iaTFs5oPSOSIXWBk5rJNuiNH9YU4gwbPH9GALcuL9U/s320/fan_temp_adc.png" width="320" /></a></div>
<br />
Temperature sensing is provided by the AD8495 k-type thermocouple amplifier. I did not write my own driver for it, I just used code already made available by <a href="http://adafruit.com/" target="_blank">http://adafruit.com/</a> .<br />
<br />
This is the board layout:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCl-rX7dB98-805UlmfCWOxiRyhhAiGhyphenhyphentyRKLD9PfPVACfbHfvRQYerF4fAhY-dhh4faO5lhdjNUOFv1W_FXWk9PWvWNPnH8cgoyvDQwsPZP7WIojZ7W-S3dKJA4vbKnX_GRGBsV5lLmM/s1600/fan_pwm.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="292" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCl-rX7dB98-805UlmfCWOxiRyhhAiGhyphenhyphentyRKLD9PfPVACfbHfvRQYerF4fAhY-dhh4faO5lhdjNUOFv1W_FXWk9PWvWNPnH8cgoyvDQwsPZP7WIojZ7W-S3dKJA4vbKnX_GRGBsV5lLmM/s640/fan_pwm.png" width="640" /></a></div>
<br />
For this board, the code and files can be found at <a href="https://github.com/andete/blog-stuff/tree/master/HPLEDRF2/temp_fan" target="_blank">https://github.com/andete/blog-stuff/tree/master/HPLEDRF2/temp_fan</a> .<br />
<br />
<h3>
Boards</h3>
<div>
I ordered boards from <a href="http://seeedstudio.com/" target="_blank">http://seeedstudio.com</a>. They took slightly longer then 2 weeks to arrive counting from first order date which is very reasonable given that they have to come from China. Pricing is also extremely competitive.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfRl-5p7JfMLovysuOIzIEAVxLCfzoF4mBUE8h3s-eYxqbxR7FUe6boicvnCDHRSodCTdyqgQ9d76WNFwQzJ4iGkO84Hqzbx7_9IruLNd4uSSy4OY_hXejMVaSzYrM3SCKFIWzjUuKWxZf/s1600/IMG_20130624_090941.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfRl-5p7JfMLovysuOIzIEAVxLCfzoF4mBUE8h3s-eYxqbxR7FUe6boicvnCDHRSodCTdyqgQ9d76WNFwQzJ4iGkO84Hqzbx7_9IruLNd4uSSy4OY_hXejMVaSzYrM3SCKFIWzjUuKWxZf/s640/IMG_20130624_090941.jpg" width="640" /></a></div>
<div>
.</div>
<div>
The boards look reasonably well. The silk screen is a bit poor at places. I did not find any electrical errors (besides my own :p ). Copper does tends to peel of when you do rework, so don't use to much heat.</div>
<div>
<br /></div>
<div>
In the meanwhile I have also other boards in progress from <a href="http://oshpark.com/" target="_blank">http://oshpark.com/</a>. I'm quite curious how long they'll take to get in Europe and make a comparison of the quality.</div>
<div>
<br /></div>
<h3>
Assembly</h3>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhe09YW2YwrgYSqeSfZ5-K2dhye1wbCzZhPf33quV2A6ZHnYy57CkGFHzvLjYYdODZk74SIh6fUdemV57VbJ4jhxq2YwqomEQFa3mVt1lHtYhSDwCLmBT3003mptDUWP8CDLTjgMexUzF_O/s1600/IMG_20130703_195018.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhe09YW2YwrgYSqeSfZ5-K2dhye1wbCzZhPf33quV2A6ZHnYy57CkGFHzvLjYYdODZk74SIh6fUdemV57VbJ4jhxq2YwqomEQFa3mVt1lHtYhSDwCLmBT3003mptDUWP8CDLTjgMexUzF_O/s640/IMG_20130703_195018.jpg" width="480" /></a></div>
<div>
<br /></div>
<div>
Here is a picture of a fan-temperature board hand assembled. It went pretty well.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKikKMadUMW7XWhYsLnCI7sfetcNj_i3lRATHS2HuSJoqZtrewutLeVOyvKwQFFaDz3lipxmfc0tV06SbvIFa7jogm15bke6OOzoK8sixOo0DL-I-gX7GugpJvEMmPqx5Kg4YQ1uhYX1X8/s1600/IMG_20130704_160806.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="478" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKikKMadUMW7XWhYsLnCI7sfetcNj_i3lRATHS2HuSJoqZtrewutLeVOyvKwQFFaDz3lipxmfc0tV06SbvIFa7jogm15bke6OOzoK8sixOo0DL-I-gX7GugpJvEMmPqx5Kg4YQ1uhYX1X8/s640/IMG_20130704_160806.jpg" width="640" /></a></div>
<div>
<br /></div>
<div>
Here I'm testing temperature measurement with a k-type thermocouple.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-7NKQe6fcy9k/Uc6wL01FiOI/AAAAAAAAG4k/b7hn0WnaS_I/s1600/IMG_20130629_114856.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="480" src="http://1.bp.blogspot.com/-7NKQe6fcy9k/Uc6wL01FiOI/AAAAAAAAG4k/b7hn0WnaS_I/s640/IMG_20130629_114856.jpg" width="640" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-jEJWLlYBMZk/Uc6wO-hvT8I/AAAAAAAAG4s/hnrBAYUxayY/s1600/IMG_20130629_114737.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="480" src="http://1.bp.blogspot.com/-jEJWLlYBMZk/Uc6wO-hvT8I/AAAAAAAAG4s/hnrBAYUxayY/s640/IMG_20130629_114737.jpg" width="640" /></a></div>
<div>
<br /></div>
<div>
Here you can see the relay PWM board sitting on top of the LED driver for testing. the Lux sensor is mounted on the lid of the case sensing through a hole.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-Hvys0qvN_fU/Udbwlkn_BhI/AAAAAAAAG_o/8VcwOnzidVY/s1600/IMG_20130705_181222.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="http://1.bp.blogspot.com/-Hvys0qvN_fU/Udbwlkn_BhI/AAAAAAAAG_o/8VcwOnzidVY/s640/IMG_20130705_181222.jpg" width="480" /></a></div>
<div>
<br /></div>
<div>
Here I'm testing the entire setup with LED driver and LED PWM board below and temperature-fan board sitting on top of the stairs.</div>
<div>
<br /></div>
<div>
It's all starting to work!</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-zN-UIC1JcXM/UepkjOcNzWI/AAAAAAAAHOc/OSI-3W9Jx9Y/s1600/img_0001.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="424" src="http://4.bp.blogspot.com/-zN-UIC1JcXM/UepkjOcNzWI/AAAAAAAAHOc/OSI-3W9Jx9Y/s640/img_0001.jpg" width="640" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-CgQpXP2bOFM/UepkjddvWPI/AAAAAAAAHOg/o7SkO6D8mgI/s1600/img_0002.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="424" src="http://1.bp.blogspot.com/-CgQpXP2bOFM/UepkjddvWPI/AAAAAAAAHOg/o7SkO6D8mgI/s640/img_0002.jpg" width="640" /></a></div>
<div>
<br /></div>
<div>
As I want two of these lamps in my living, I started on assembly of the second lamp. I've slight changed the mounting. in the first lamp I used screws and aluminium to put the LED die in place. Here I've used termo-conductive glue to place the die on the plate. This has a big advantage that there are no screws in the way and the heat sink sits snugly on the other side of the plate. Also I've opted to mount the fan directly on the heat sink for simplicity.</div>
<div>
<br /></div>
<div>
On the top picture you can nicely see the thermocouple mounted on the LED die. Insulated with kapton tape.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/--jkpKXzaof4/Ue0ZiEqzdoI/AAAAAAAAHQk/rO5Pyc1Hw74/s1600/IMG_20130722_133652.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="480" src="http://4.bp.blogspot.com/--jkpKXzaof4/Ue0ZiEqzdoI/AAAAAAAAHQk/rO5Pyc1Hw74/s640/IMG_20130722_133652.jpg" width="640" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
With both lamps working fine, it's time to clean up the assembly for their final wiring. Wiring is always such a mess...</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-ckEG7fM4Mow/Ue1kz0Z1UwI/AAAAAAAAHRg/E8CcLhr71Vw/s1600/IMG_20130722_185745.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="480" src="http://4.bp.blogspot.com/-ckEG7fM4Mow/Ue1kz0Z1UwI/AAAAAAAAHRg/E8CcLhr71Vw/s640/IMG_20130722_185745.jpg" width="640" /></a></div>
<div>
<br /></div>
<div>
Here is the final wiring for the LED PWM boards and the LED drivers. Wires will of course be flattened when they're at their final location, and the cases will be closed. At this point I finished up the firmware as once the lamps are in place it will be next to impossible to reach the boards.</div>
<div>
<br /></div>
<div>
So all that is left is mounting them on a piece of wood and hanging the lamps on their final spot!</div>
Anonymoushttp://www.blogger.com/profile/09143890844136884489noreply@blogger.com0tag:blogger.com,1999:blog-8979045496387455785.post-4385418987443062022013-05-31T12:01:00.000+02:002013-05-31T12:01:17.148+02:00BufferSerial: let Arduino Stream writes go in a bufferWhen you have existing code that uses an Arduino Stream like "Serial" or "SoftwareSerial" data is written part by part on the serial device. Sometimes you want to collect different parts first, maybe adding something like a checksum and only then send everything on one go. By using the BufferSerial construct you can just keep the existing code, pass it the BufferSerial instead of your normal Serial and afterward use the content of the buffer, and send it as one big blob.<br />
<br />
A simple example:
<br />
<pre class="prettyprint">uint8_t mybuffer[32];
BufferSerial bs(mybuffer, 32);
bs.print((int)42);
bs.write(' ');
bs.print(127, HEX);
bs.print("hello");
Serial.println(bs);
</pre>
<br />
The code for BufferSerial is really simple and can be found at: <a href="https://github.com/andete/blog-stuff/tree/master/BUFSER1" target="_blank">https://github.com/andete/blog-stuff/tree/master/BUFSER1</a> .Anonymoushttp://www.blogger.com/profile/09143890844136884489noreply@blogger.com2