<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>work in progress &#187; Electronics</title>
	<atom:link href="http://www.workinprogress.ca/category/electronics/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.workinprogress.ca</link>
	<description>of patrick sébastien</description>
	<lastBuildDate>Fri, 23 Dec 2011 20:56:32 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>p-waves physical feedback</title>
		<link>http://www.workinprogress.ca/p-waves-physical-feedback/</link>
		<comments>http://www.workinprogress.ca/p-waves-physical-feedback/#comments</comments>
		<pubDate>Thu, 24 Mar 2011 17:16:22 +0000</pubDate>
		<dc:creator>psc</dc:creator>
				<category><![CDATA[Electronics]]></category>

		<guid isPermaLink="false">http://www.workinprogress.ca/?p=1136</guid>
		<description><![CDATA[on march 11 my apartment in tokyo was shook by an earthquake of magnitude 9.0: since i don&#8217;t have a mobile phone (i must be the only one in japan without a keitai) i wasn&#8217;t aware of the incoming earthquake and my software was useless (being alert 10 minutes after the earthquake): by detecting the [...]]]></description>
			<content:encoded><![CDATA[<p>on march 11 my apartment in tokyo was shook by an earthquake of magnitude 9.0:</p>
<p><iframe title="YouTube video player" width="560" height="349" src="http://www.youtube.com/embed/i6U-N0W5Zkc?rel=0&#038;wmode=transparent" frameborder="0" allowfullscreen></iframe></p>
<p>since i don&#8217;t have a mobile phone (i must be the only one in japan without a keitai) i wasn&#8217;t aware of the incoming earthquake and my software was useless (being alert 10 minutes after the earthquake):</p>
<p><iframe src="http://player.vimeo.com/video/13615727" width="560" height="315" frameborder="0"></iframe></p>
<p>by detecting the <a href="http://en.wikipedia.org/wiki/Seismic_wave#P-waves">primary waves</a> we know in how many seconds (depending on the epicenter location) an earthquake will occur. i don&#8217;t know if it&#8217;s possible to build a p waves monitoring device (anyone?), but for now i&#8217;m using a <a href="http://www.estrat.co.jp/download.html">free software</a> (windows &#038; japanese only) that send me an alert (no hardware required).</p>
<p>connecting the software to a microcontroller was not that hard, but since i don&#8217;t want to boot in windows just for monitoring the p waves i had to hack little. grosso modo: <a href="http://www.virtualbox.org/">virtual box</a> (windows in linux) -> <a href="http://www.autoitscript.com/site/autoit/">autoit</a> (checking for a p waves popup) -> create file <- linux bash checking for new file -> send serial command to arduino -> physical feedback.</p>
<p><iframe title="YouTube video player" width="560" height="349" src="http://www.youtube.com/embed/oiP9QCS-8ig?rel=0&#038;wmode=transparent" frameborder="0" allowfullscreen></iframe></p>
<p><strong>please make a donation to the japanese red cross society</strong></p>
<p><a href="http://www.google.com/crisisresponse/japanquake2011.html"><img border="0" src="http://www.redcross.org/www-files/psabanners/PacificTsunami/468x60.jpg" alt="Japan Earthquake and Pacific Tsunami"></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.workinprogress.ca/p-waves-physical-feedback/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>vibrating art</title>
		<link>http://www.workinprogress.ca/vibrating-art/</link>
		<comments>http://www.workinprogress.ca/vibrating-art/#comments</comments>
		<pubDate>Sun, 19 Dec 2010 18:23:16 +0000</pubDate>
		<dc:creator>psc</dc:creator>
				<category><![CDATA[Electronics]]></category>

		<guid isPermaLink="false">http://www.workinprogress.ca/?p=876</guid>
		<description><![CDATA[the idea is simple: take an old electric toothbrush; add a led and a vibrator; shape something around it; i am using polycaprolactone (FDA approuved). the schematic is pretty simple, but i had to play with the capacitor and inductor to get more power into the vibrator. it&#8217;s overkill to use an attiny for cycling [...]]]></description>
			<content:encoded><![CDATA[<p>the idea is simple:</p>
<ul>
<li>take an old electric toothbrush;</li>
<li>add a led and a vibrator;</li>
<li>shape something around it;</li>
</ul>
<p>i am using polycaprolactone (FDA approuved). the schematic is pretty simple, but i had to play with the capacitor and inductor to get more power into the vibrator. it&#8217;s overkill to use an attiny for cycling the colors of the led (i didn&#8217;t know that you can buy RGB led with built-in pwm). even so, i am sharing the small code, maybe it can be useful to someone. since i am using an electric toothbrush there&#8217;s no physical connection to recharge it, thus completely waterproof. i will need to remelt the polycaprolactone to change the battery someday.</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="540" height="405" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/vE1pPWRUmbs&amp;hl=en_US&amp;fs=1?rel=0&amp;hd=1" /><param name="allowfullscreen" value="true" /><param name="wmode" value="transparent" /><embed type="application/x-shockwave-flash" width="540" height="405" src="http://www.youtube.com/v/vE1pPWRUmbs&amp;hl=en_US&amp;fs=1?rel=0&amp;hd=1" wmode="transparent" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>

<a href='http://www.workinprogress.ca/vibrating-art/va_bundle/' title='va_bundle'><img width="150" height="150" src="http://www.workinprogress.ca/wp-content/uploads/va_bundle-150x150.jpg" class="attachment-thumbnail" alt="va_bundle" title="va_bundle" /></a>
<a href='http://www.workinprogress.ca/vibrating-art/va_onrecharge/' title='va_onrecharge'><img width="150" height="150" src="http://www.workinprogress.ca/wp-content/uploads/va_onrecharge-150x150.jpg" class="attachment-thumbnail" alt="va_onrecharge" title="va_onrecharge" /></a>
<a href='http://www.workinprogress.ca/vibrating-art/va_schematic/' title='va_schematic'><img width="150" height="150" src="http://www.workinprogress.ca/wp-content/uploads/va_schematic-150x150.jpg" class="attachment-thumbnail" alt="va_schematic" title="va_schematic" /></a>
<a href='http://www.workinprogress.ca/vibrating-art/va_withvl/' title='va_withvl'><img width="150" height="150" src="http://www.workinprogress.ca/wp-content/uploads/va_withvl-150x150.jpg" class="attachment-thumbnail" alt="va_withvl" title="va_withvl" /></a>

<p></p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"> <span style="color: #339933;">#define F_CPU 9600000UL</span>
 <span style="color: #339933;">#include &lt;avr/io.h&gt;</span>
 <span style="color: #339933;">#include &lt;util/delay.h&gt;</span>
 <span style="color: #339933;">#define LED PB0</span>
 <span style="color: #339933;">#define LED2 PB1</span>
 <span style="color: #993333;">int</span> i<span style="color: #339933;">;</span>
&nbsp;
 <span style="color: #993333;">int</span> main <span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span>
 <span style="color: #009900;">&#123;</span>
	 DDRB <span style="color: #339933;">=</span> <span style="color: #208080;">0xff</span><span style="color: #339933;">;</span>
	 TCCR0A <span style="color: #339933;">|=</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span> <span style="color: #339933;">&lt;&lt;</span> COM0A1<span style="color: #009900;">&#41;</span> <span style="color: #339933;">|</span> <span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span> <span style="color: #339933;">&lt;&lt;</span> COM0A0<span style="color: #009900;">&#41;</span> <span style="color: #339933;">|</span> <span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span> <span style="color: #339933;">&lt;&lt;</span> COM0B1<span style="color: #009900;">&#41;</span> <span style="color: #339933;">|</span> <span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span> <span style="color: #339933;">&lt;&lt;</span> COM0B0<span style="color: #009900;">&#41;</span> <span style="color: #339933;">|</span> <span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span> <span style="color: #339933;">&lt;&lt;</span> WGM01<span style="color: #009900;">&#41;</span> <span style="color: #339933;">|</span> <span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span> <span style="color: #339933;">&lt;&lt;</span> WGM00<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// WGM01 - WGM00 (set fast PWM)</span>
	 OCR0A <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// initialize Output Compare Register A to 0</span>
	 OCR0B <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
	 TCCR0B <span style="color: #339933;">|=</span> <span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span> <span style="color: #339933;">&lt;&lt;</span> CS01<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// Start timer at Fcpu / 256</span>
&nbsp;
	 <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">;;</span><span style="color: #009900;">&#41;</span>
	 <span style="color: #009900;">&#123;</span>
		 <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span> <span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">255</span> <span style="color: #339933;">;</span> i<span style="color: #339933;">++</span> <span style="color: #009900;">&#41;</span> <span style="color: #666666; font-style: italic;">// For loop (Up counter 0 - 255)</span>
		 <span style="color: #009900;">&#123;</span>
			  OCR0A <span style="color: #339933;">=</span> i<span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// Update Output Compare Register (PWM 0 - 255)</span>
			 _delay_ms<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">8</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		 <span style="color: #009900;">&#125;</span>
		 <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">255</span> <span style="color: #339933;">;</span> i <span style="color: #339933;">&gt;</span> <span style="color: #0000dd;">1</span> <span style="color: #339933;">;</span> i<span style="color: #339933;">--</span> <span style="color: #009900;">&#41;</span> <span style="color: #666666; font-style: italic;">// For loop (down counter 255 - 0 )</span>
		 <span style="color: #009900;">&#123;</span>
			 OCR0B <span style="color: #339933;">=</span> i<span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// Update Output Compare Register (PWM 0 - 255)</span>
			 _delay_ms<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">8</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		 <span style="color: #009900;">&#125;</span>
		 <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">255</span> <span style="color: #339933;">;</span> i <span style="color: #339933;">&gt;</span> <span style="color: #0000dd;">1</span> <span style="color: #339933;">;</span> i<span style="color: #339933;">--</span> <span style="color: #009900;">&#41;</span> <span style="color: #666666; font-style: italic;">// For loop (down counter 255 - 0 )</span>
		 <span style="color: #009900;">&#123;</span>
			  OCR0A <span style="color: #339933;">=</span> i<span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// Update Output Compare Register (PWM 0 - 255)</span>
			 _delay_ms<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">8</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		 <span style="color: #009900;">&#125;</span>
		 <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span> <span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">255</span> <span style="color: #339933;">;</span> i<span style="color: #339933;">++</span> <span style="color: #009900;">&#41;</span> <span style="color: #666666; font-style: italic;">// For loop (Up counter 0 - 255)</span>
		 <span style="color: #009900;">&#123;</span>
			  OCR0B <span style="color: #339933;">=</span> i<span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// Update Output Compare Register (PWM 0 - 255)</span>
			 _delay_ms<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">8</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		 <span style="color: #009900;">&#125;</span>
	 <span style="color: #009900;">&#125;</span>
 <span style="color: #009900;">&#125;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.workinprogress.ca/vibrating-art/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>video tour of akihabara</title>
		<link>http://www.workinprogress.ca/video-tour-of-akihabara/</link>
		<comments>http://www.workinprogress.ca/video-tour-of-akihabara/#comments</comments>
		<pubDate>Sat, 25 Sep 2010 02:55:29 +0000</pubDate>
		<dc:creator>psc</dc:creator>
				<category><![CDATA[Electronics]]></category>

		<guid isPermaLink="false">http://www.workinprogress.ca/?p=820</guid>
		<description><![CDATA[if you are curious to see the electronic town (Akihabara) in Tokyo:]]></description>
			<content:encoded><![CDATA[<p>if you are curious to see the electronic town (Akihabara) in Tokyo:<br />
<a href="http://www.workinprogress.ca/akihabara"><img class="alignnone size-full wp-image-821" title="akihabara" src="http://www.workinprogress.ca/wp-content/uploads/akihabara.jpg" alt="" width="533" height="454" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.workinprogress.ca/video-tour-of-akihabara/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>cheap avr intervalometer</title>
		<link>http://www.workinprogress.ca/avr-intervalometer/</link>
		<comments>http://www.workinprogress.ca/avr-intervalometer/#comments</comments>
		<pubDate>Sat, 24 Jul 2010 08:38:21 +0000</pubDate>
		<dc:creator>psc</dc:creator>
				<category><![CDATA[Blender]]></category>
		<category><![CDATA[Electronics]]></category>

		<guid isPermaLink="false">http://www.workinprogress.ca/?p=755</guid>
		<description><![CDATA[now that i have a digital camera (but my heart will always belong to film-based photography) i can do time lapse photography. sadly the firmware of my camera isn&#8217;t supporting this feature, so i had to build an intervalometer. i didn&#8217;t want to use an arduino (overkill &#38; pricy), so i went with an attiny45, [...]]]></description>
			<content:encoded><![CDATA[<p>now that i have a digital camera (but my heart will always belong to film-based photography) i can do time lapse photography. sadly the firmware of my camera isn&#8217;t supporting this feature, so i had to build an <a href="http://en.wikipedia.org/wiki/Intervalometer" target="_blank">intervalometer</a>. i didn&#8217;t want to use an arduino (overkill &amp; pricy), so i went with an attiny45, a generic optocoupler, a voltage regulator and a potentiometer for adjusting the timer from 1 second to 1 minute.</p>
<p>i just found out that it&#8217;s possible to power the avr from the camera (focus ring). have a look at this complete and small solution: <a href="http://www.doc-diy.net/photo/hdr-jack/">http://www.doc-diy.net/photo/hdr-jack/</a></p>

<a href='http://www.workinprogress.ca/avr-intervalometer/intervalometer_1/' title='intervalometer_1'><img width="150" height="150" src="http://www.workinprogress.ca/wp-content/uploads/intervalometer_1-150x150.jpg" class="attachment-thumbnail" alt="intervalometer_1" title="intervalometer_1" /></a>
<a href='http://www.workinprogress.ca/avr-intervalometer/intervalometer_3/' title='intervalometer_3'><img width="150" height="150" src="http://www.workinprogress.ca/wp-content/uploads/intervalometer_3-150x150.jpg" class="attachment-thumbnail" alt="intervalometer_3" title="intervalometer_3" /></a>
<a href='http://www.workinprogress.ca/avr-intervalometer/avr_intervalometer_schematic/' title='avr_intervalometer_schematic'><img width="150" height="150" src="http://www.workinprogress.ca/wp-content/uploads/avr_intervalometer_schematic-150x150.png" class="attachment-thumbnail" alt="avr_intervalometer_schematic" title="avr_intervalometer_schematic" /></a>


<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//Intervalometer from 1 second to 1 minute</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//Author: Patrick Sebastien Coulombe</span>
<span style="color: #666666; font-style: italic;">//Website: www.workinprogress.ca</span>
<span style="color: #666666; font-style: italic;">//Date: 2010-07-24</span>
&nbsp;
<span style="color: #339933;">#define F_CPU 8000000</span>
<span style="color: #339933;">#include &lt;avr/io.h&gt;</span>
<span style="color: #339933;">#include &lt;util/delay.h&gt;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// use PB2 for led, pin 7</span>
<span style="color: #339933;">#define LED_BIT 2</span>
<span style="color: #666666; font-style: italic;">// select ADC2, PB4, pin 3</span>
<span style="color: #339933;">#define CHANNEL 2</span>
<span style="color: #666666; font-style: italic;">// shutter on (in ms)</span>
<span style="color: #339933;">#define HOLD 300 </span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Return the 10bit value of the selected adc channel.</span>
<span style="color: #993333;">uint16_t</span> get_adc<span style="color: #009900;">&#40;</span><span style="color: #993333;">uint8_t</span> channel<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// ADC setup</span>
	ADCSRA <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span> <span style="color: #339933;">&lt;&lt;</span> ADEN<span style="color: #009900;">&#41;</span> <span style="color: #339933;">|</span> <span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span> <span style="color: #339933;">&lt;&lt;</span> ADPS1<span style="color: #009900;">&#41;</span> <span style="color: #339933;">|</span> <span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span> <span style="color: #339933;">&lt;&lt;</span> ADPS0<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// select channel</span>
	ADMUX <span style="color: #339933;">=</span> channel<span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// warm up the ADC, discard the first conversion</span>
	ADCSRA <span style="color: #339933;">|=</span> <span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span> <span style="color: #339933;">&lt;&lt;</span> ADSC<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span>ADCSRA <span style="color: #339933;">&amp;</span> <span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span> <span style="color: #339933;">&lt;&lt;</span> ADSC<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
&nbsp;
	ADCSRA <span style="color: #339933;">|=</span> <span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span> <span style="color: #339933;">&lt;&lt;</span> ADSC<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// start single conversion</span>
	<span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span>ADCSRA <span style="color: #339933;">&amp;</span> <span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span> <span style="color: #339933;">&lt;&lt;</span> ADSC<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// wait until conversion is done</span>
&nbsp;
	<span style="color: #b1b100;">return</span> ADCW<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Scale</span>
<span style="color: #993333;">long</span> map<span style="color: #009900;">&#40;</span><span style="color: #993333;">long</span> x<span style="color: #339933;">,</span> <span style="color: #993333;">long</span> in_min<span style="color: #339933;">,</span> <span style="color: #993333;">long</span> in_max<span style="color: #339933;">,</span> <span style="color: #993333;">long</span> out_min<span style="color: #339933;">,</span> <span style="color: #993333;">long</span> out_max<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #b1b100;">return</span> <span style="color: #009900;">&#40;</span>x <span style="color: #339933;">-</span> in_min<span style="color: #009900;">&#41;</span> <span style="color: #339933;">*</span> <span style="color: #009900;">&#40;</span>out_max <span style="color: #339933;">-</span> out_min<span style="color: #009900;">&#41;</span> <span style="color: #339933;">/</span> <span style="color: #009900;">&#40;</span>in_max <span style="color: #339933;">-</span> in_min<span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> out_min<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Main program</span>
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// vars</span>
	<span style="color: #993333;">uint16_t</span> adcvalue <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
	<span style="color: #993333;">uint16_t</span> i<span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// define LED as outputs</span>
	DDRB <span style="color: #339933;">|=</span> <span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span> <span style="color: #339933;">&lt;&lt;</span> LED_BIT<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>	
&nbsp;
	<span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>	
&nbsp;
		<span style="color: #666666; font-style: italic;">//release the shutter</span>
		PORTB <span style="color: #339933;">|=</span> <span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span> <span style="color: #339933;">&lt;&lt;</span> LED_BIT<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #666666; font-style: italic;">//exposure length</span>
		<span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i<span style="color: #339933;">=</span><span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> i<span style="color: #339933;">&lt;</span>HOLD<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> 
			_delay_ms<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
		<span style="color: #009900;">&#125;</span>
		PORTB <span style="color: #339933;">&amp;=</span> ~<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span> <span style="color: #339933;">&lt;&lt;</span> LED_BIT<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #666666; font-style: italic;">//interval time (using a potentiometer to adjust)</span>
		adcvalue <span style="color: #339933;">=</span> map<span style="color: #009900;">&#40;</span>get_adc<span style="color: #009900;">&#40;</span>CHANNEL<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">1023</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">60</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		adcvalue <span style="color: #339933;">=</span> adcvalue <span style="color: #339933;">*</span> <span style="color: #0000dd;">1000</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #666666; font-style: italic;">//one way to achieve long delay</span>
		<span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i<span style="color: #339933;">=</span><span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> i<span style="color: #339933;">&lt;</span>adcvalue<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> 
			_delay_ms<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
		<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #009900;">&#125;</span>
	<span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Time lapse test (3 hours) from my balcony.</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="540" height="405" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="wmode" value="transparent" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/mKEQjxkCzD4&amp;hl=en_US&amp;fs=1?rel=0&amp;hd=1" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="540" height="405" src="http://www.youtube.com/v/mKEQjxkCzD4&amp;hl=en_US&amp;fs=1?rel=0&amp;hd=1" allowscriptaccess="always" allowfullscreen="true" wmode="transparent"></embed></object></p>
<p>I used Blender for making the tilt / shift effect. Here&#8217;s the <a href="http://www.workinprogress.ca/wp-content/uploads/blendertiltshift.tar.gz">source</a> of the Blender file.</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="540" height="405" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="wmode" value="transparent" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/qpac5wb7mAE&amp;hl=en_US&amp;fs=1?rel=0&amp;hd=1" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="540" height="405" src="http://www.youtube.com/v/qpac5wb7mAE&amp;hl=en_US&amp;fs=1?rel=0&amp;hd=1" allowscriptaccess="always" allowfullscreen="true" wmode="transparent"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://www.workinprogress.ca/avr-intervalometer/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>singing birds</title>
		<link>http://www.workinprogress.ca/singing-birds/</link>
		<comments>http://www.workinprogress.ca/singing-birds/#comments</comments>
		<pubDate>Tue, 13 Apr 2010 04:36:59 +0000</pubDate>
		<dc:creator>psc</dc:creator>
				<category><![CDATA[Electronics]]></category>

		<guid isPermaLink="false">http://www.workinprogress.ca/?p=706</guid>
		<description><![CDATA[10 watts amplifier with built-in 16-bit / 48kHz RIFF-WAVE player (music on a SD-CARD). 2 servos for controlling the beaks. I did this project mostly to learn stuff. The result is a bit stupid. VIDEO: PHOTOS: Schematic &#038; Board (Kicad) How to filter PWM for music sd player source code /*---------------------------------------------------------------*/ /* 8-pin SD audio [...]]]></description>
			<content:encoded><![CDATA[<p>10 watts amplifier with built-in 16-bit / 48kHz RIFF-WAVE player (<a href="http://elm-chan.org/works/sd8p/report.html" target="_blank">music on a SD-CARD</a>). 2 servos for controlling the beaks. I did this project mostly to learn stuff. The result is a bit stupid.</p>
<p><strong>VIDEO:</strong><br />
<object width="480" height="385"><param name="movie" value="http://www.youtube.com/v/rEM_cyZhxQU?fs=1&amp;hl=en_US&amp;rel=0"></param><param name="wmode" value="transparent" /></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/rEM_cyZhxQU?fs=1&amp;hl=en_US&amp;rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" wmode="transparent" allowfullscreen="true" width="480" height="385"></embed></object></p>
<p><strong>PHOTOS:</strong><br />

<a href='http://www.workinprogress.ca/singing-birds/p4120089/' title='passive crossover'><img width="150" height="150" src="http://www.workinprogress.ca/wp-content/uploads/P4120089-150x150.jpg" class="attachment-thumbnail" alt="passive crossover" title="passive crossover" /></a>
<a href='http://www.workinprogress.ca/singing-birds/p4130093/' title='back - 2 mini servo'><img width="150" height="150" src="http://www.workinprogress.ca/wp-content/uploads/P4130093-150x150.jpg" class="attachment-thumbnail" alt="back - 2 mini servo" title="back - 2 mini servo" /></a>
<a href='http://www.workinprogress.ca/singing-birds/p4130094/' title='single-side homemade PCB'><img width="150" height="150" src="http://www.workinprogress.ca/wp-content/uploads/P4130094-150x150.jpg" class="attachment-thumbnail" alt="single-side homemade PCB" title="single-side homemade PCB" /></a>
<a href='http://www.workinprogress.ca/singing-birds/p4130095/' title='front'><img width="150" height="150" src="http://www.workinprogress.ca/wp-content/uploads/P4130095-150x150.jpg" class="attachment-thumbnail" alt="front" title="front" /></a>
<a href='http://www.workinprogress.ca/singing-birds/blender/' title='i used blender like a CAD software'><img width="150" height="150" src="http://www.workinprogress.ca/wp-content/uploads/blender-150x150.jpg" class="attachment-thumbnail" alt="i used blender like a CAD software" title="i used blender like a CAD software" /></a>
<a href='http://www.workinprogress.ca/singing-birds/board/' title='attiny85 - attiny24 - tpa1517ne - pwm filter - opamp'><img width="150" height="150" src="http://www.workinprogress.ca/wp-content/uploads/board-150x150.jpg" class="attachment-thumbnail" alt="attiny85 - attiny24 - tpa1517ne - pwm filter - opamp" title="attiny85 - attiny24 - tpa1517ne - pwm filter - opamp" /></a>
<a href='http://www.workinprogress.ca/singing-birds/schematic-2/' title='schematic - done in kicad'><img width="150" height="150" src="http://www.workinprogress.ca/wp-content/uploads/schematic1-150x150.jpg" class="attachment-thumbnail" alt="schematic - done in kicad" title="schematic - done in kicad" /></a>
</p>
<p>
<a href="http://www.workinprogress.ca/wp-content/uploads/sb.zip">Schematic &#038; Board</a> (Kicad)<br />
<a href="http://www.workinprogress.ca/filtering-pwm-for-music/">How to filter PWM for music</a>
</p>
<p>sd player source code</p>
<p><pre><pre class="brush:c">
/*---------------------------------------------------------------*/
/* 8-pin SD audio player R0.02&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (C)ChaN, 2009 */
/*---------------------------------------------------------------*/

#include &lt;avr/io.h&gt;
#include &lt;avr/interrupt.h&gt;
#include &lt;avr/sleep.h&gt;
#include &lt;avr/wdt.h&gt;
#include &lt;string.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;stdio.h&gt;
#include &quot;diskio.h&quot;
#include &quot;pff.h&quot;

char strbuff[10];
unsigned int position = 0;
unsigned long count = 0;
unsigned int nbwave = 0;

#define FCC(c1,c2,c3,c4)&nbsp;&nbsp;(((DWORD)c4&lt;&lt;24)+((DWORD)c3&lt;&lt;16)+((WORD)c2&lt;&lt;8)+(BYTE)c1)&nbsp;&nbsp;/* FourCC */

/*---------------------------------------------------------*/
/* Work Area&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */
/*---------------------------------------------------------*/

volatile BYTE FifoRi, FifoWi, FifoCt;&nbsp;&nbsp;/* FIFO controls */

BYTE Buff[256];&nbsp;&nbsp;&nbsp;&nbsp;/* Wave output FIFO */

FATFS fs;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* File system object */
DIR dir;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Directory object */
FILINFO fno;&nbsp;&nbsp;&nbsp;&nbsp;/* File information */

WORD rb;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Return value. Put this here to avoid bugs of avr-gcc */

EMPTY_INTERRUPT(WDT_vect);

/*---------------------------------------------------------*/

static
DWORD load_header (void)&nbsp;&nbsp;/* 0:Invalid format, 1:I/O error, &gt;1:Number of samples */
{
&nbsp;&nbsp;DWORD fcc, sz;
&nbsp;&nbsp;UINT i;
&nbsp;&nbsp;FRESULT res;

&nbsp;&nbsp;res = pf_read(Buff, 256, &amp;rb);&nbsp;&nbsp;&nbsp;&nbsp;/* Load file header (256 bytes) */
&nbsp;&nbsp;if (res) return 1;

&nbsp;&nbsp;if (rb != 256 || LD_DWORD(Buff+8) != FCC(&#039;W&#039;,&#039;A&#039;,&#039;V&#039;,&#039;E&#039;)) return 0;

&nbsp;&nbsp;i = 12;
&nbsp;&nbsp;while (i &lt; 200) {
&nbsp;&nbsp;&nbsp;&nbsp;fcc = LD_DWORD(&amp;Buff[i]);&nbsp;&nbsp;/* FCC */
&nbsp;&nbsp;&nbsp;&nbsp;sz = LD_DWORD(&amp;Buff[i+4]);&nbsp;&nbsp;/* Chunk size */
&nbsp;&nbsp;&nbsp;&nbsp;i += 8;
&nbsp;&nbsp;&nbsp;&nbsp;switch (fcc) {

&nbsp;&nbsp;&nbsp;&nbsp;case FCC(&#039;f&#039;,&#039;m&#039;,&#039;t&#039;,&#039; &#039;) :&nbsp;&nbsp;&nbsp;&nbsp;/* &#039;fmt &#039; chunk */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (sz &gt; 100 || sz &lt; 16)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Check chunk size */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (Buff[i+0] != 1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Check coding type (1) */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (Buff[i+2] != 1 &amp;&amp; Buff[i+2] != 2)&nbsp;&nbsp;/* Check channels (1/2) */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GPIOR0 = Buff[i+2];&nbsp;&nbsp;&nbsp;&nbsp;/* Channel flag */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (Buff[i+14] != 8 &amp;&amp; Buff[i+14] != 16)&nbsp;&nbsp;/* Check resolution (8/16) */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GPIOR0 |= Buff[i+14];&nbsp;&nbsp;/* Resolution flag */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OCR0A = (BYTE)(F_CPU / 8 / LD_WORD(&amp;Buff[i+4])) - 1;&nbsp;&nbsp;/* Sampling freq */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;

&nbsp;&nbsp;&nbsp;&nbsp;case FCC(&#039;f&#039;,&#039;a&#039;,&#039;c&#039;,&#039;t&#039;) :&nbsp;&nbsp;&nbsp;&nbsp;/* &#039;fact&#039; chunk (skip) */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;

&nbsp;&nbsp;&nbsp;&nbsp;case FCC(&#039;d&#039;,&#039;a&#039;,&#039;t&#039;,&#039;a&#039;) :&nbsp;&nbsp;&nbsp;&nbsp;/* &#039;data&#039; chunk (start to play) */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fs.fptr = i;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return sz;

&nbsp;&nbsp;&nbsp;&nbsp;default :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Unknown chunk (error) */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;i += sz;
&nbsp;&nbsp;}

&nbsp;&nbsp;return 0;
}

static
UINT play (
&nbsp;&nbsp;const char *fn
)
{
&nbsp;&nbsp;DWORD sz;
&nbsp;&nbsp;FRESULT res;
&nbsp;&nbsp;BYTE sw;
&nbsp;&nbsp;WORD btr;

&nbsp;&nbsp;if ((res = pf_open(fn)) == FR_OK) {
&nbsp;&nbsp;&nbsp;&nbsp;sz = load_header();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Load file header */
&nbsp;&nbsp;&nbsp;&nbsp;if (sz &lt; 256) return (UINT)sz;

&nbsp;&nbsp;&nbsp;&nbsp;if (!TCCR1) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Enable audio out if not enabled */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PLLCSR = 0b00000110;&nbsp;&nbsp;/* Select PLL clock for TC1.ck */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GTCCR =&nbsp;&nbsp;0b01100000;&nbsp;&nbsp;/* Enable TC1.OCB as PWM out (L-ch) */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OCR1B = 128; OCR1A = 128;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TCCR1 = STEREO ? 0b01100001 : 0b00000001;&nbsp;&nbsp;/* Start TC1 with TC1.OCA is enabled as PWM out (R-ch) */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TCCR0A = 0b00000010;&nbsp;&nbsp;/* Enable TC0.ck = 2MHz as interval timer */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TCCR0B = 0b00000010;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TIMSK = _BV(OCIE0A);
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;FifoCt = 0; FifoRi = 0; FifoWi = 0;&nbsp;&nbsp;&nbsp;&nbsp;/* Reset FIFO */
&nbsp;&nbsp;&nbsp;&nbsp;pf_read(0, 512 - fs.fptr, &amp;rb);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Snip sector unaligned part */
&nbsp;&nbsp;&nbsp;&nbsp;sz -= rb;

&nbsp;&nbsp;&nbsp;&nbsp;sw = 1;&nbsp;&nbsp;&nbsp;&nbsp;/* Button status flag */
&nbsp;&nbsp;&nbsp;&nbsp;do {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Forward audio data */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;btr = (sz &gt; 1024) ? 1024 : (WORD)sz;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;res = pf_read(0, btr, &amp;rb);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (res != FR_OK || btr != rb) break;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sz -= rb;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Check button down and break on button down */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sw &lt;&lt;= 1;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//if (bit_is_clear(PINB, 0) &amp;&amp; ++sw == 1) break;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (bit_is_clear(PINB, 0) &amp;&amp; ++sw == 1) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;count = 0;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;do { 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;count++;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wdt_reset();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} while (bit_is_clear(PINB, 0));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(count &gt; 500000) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;position--;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;position--;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wdt_reset();
&nbsp;&nbsp;&nbsp;&nbsp;} while (rb == 1024);&nbsp;&nbsp;/* Repeat until all data read */
&nbsp;&nbsp;}

&nbsp;&nbsp;while (FifoCt) ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Wait for FIFO empty */
&nbsp;&nbsp;OCR1A = 128; OCR1B = 128;

&nbsp;&nbsp;return res;
}

long smallrandom(long howbig)
{
&nbsp;&nbsp;if (howbig == 0) {
&nbsp;&nbsp;&nbsp;&nbsp;return 0;
&nbsp;&nbsp;}
&nbsp;&nbsp;return random() % howbig;
}

long rangerandom(long howsmall, long howbig)
{
&nbsp;&nbsp;if (howsmall &gt;= howbig) {
&nbsp;&nbsp;&nbsp;&nbsp;return howsmall;
&nbsp;&nbsp;}
&nbsp;&nbsp;long diff = howbig - howsmall;
&nbsp;&nbsp;return smallrandom(diff) + howsmall;
}

int main (void)
{
&nbsp;&nbsp;PORTB = 0b111011;&nbsp;&nbsp;&nbsp;&nbsp;/* Initialize port: - - H H H L H P */
&nbsp;&nbsp;DDRB&nbsp;&nbsp;= 0b111110;
&nbsp;&nbsp;
&nbsp;&nbsp;sei();
&nbsp;&nbsp;
&nbsp;&nbsp;//RANDOM (SEED)
&nbsp;&nbsp;unsigned long seednumber = 1;
&nbsp;&nbsp;unsigned char i;
&nbsp;&nbsp;ADCSRA |= (1 &lt;&lt; ADPS2) | (1 &lt;&lt; ADPS1) | (0 &lt;&lt; ADPS0);&nbsp;&nbsp;//ADC Prescalar set to 64 - 125kHz@8MHz
&nbsp;&nbsp;ADMUX |= (1 &lt;&lt; ADLAR);
&nbsp;&nbsp;ADCSRA |= (1 &lt;&lt; ADEN);&nbsp;&nbsp;// Enable ADC
&nbsp;&nbsp;&nbsp;&nbsp;for(i = 0; i &lt; 100; i++) {
&nbsp;&nbsp;&nbsp;&nbsp;wdt_reset();
&nbsp;&nbsp;&nbsp;&nbsp;ADCSRA |= (1 &lt;&lt; ADSC);&nbsp;&nbsp;// Start A2D Conversions
&nbsp;&nbsp;&nbsp;&nbsp;while (ADCSRA &amp; (1 &lt;&lt; ADSC)); 
&nbsp;&nbsp;&nbsp;&nbsp;seednumber = seednumber + ADCH;
&nbsp;&nbsp;}
&nbsp;&nbsp;ADCSRA |= (0 &lt;&lt; ADATE);
&nbsp;&nbsp;ADCSRA |= (0 &lt;&lt; ADEN);&nbsp;&nbsp;// Disable ADC
&nbsp;&nbsp;&nbsp;&nbsp;ADCSRA |= (0 &lt;&lt; ADSC);&nbsp;&nbsp;// Stop A2D Conversions
&nbsp;&nbsp;
&nbsp;&nbsp;MCUSR = 0;
&nbsp;&nbsp;WDTCR = _BV(WDE) | 0b110;&nbsp;&nbsp;/* Enable WDT reset in timeout of 1s */

&nbsp;&nbsp;BYTE res;
&nbsp;&nbsp;//mount
&nbsp;&nbsp;do {
&nbsp;&nbsp;&nbsp;&nbsp;res = pf_mount(&amp;fs);
&nbsp;&nbsp;&nbsp;&nbsp;wdt_reset();
&nbsp;&nbsp;&nbsp;&nbsp;seednumber++;
&nbsp;&nbsp;} while (res != FR_OK);
&nbsp;&nbsp;
&nbsp;&nbsp;Buff[0] = 0;
&nbsp;&nbsp;do {
&nbsp;&nbsp;&nbsp;&nbsp;res = pf_opendir(&amp;dir, (char*)Buff);
&nbsp;&nbsp;&nbsp;&nbsp;wdt_reset();
&nbsp;&nbsp;&nbsp;&nbsp;seednumber++;
&nbsp;&nbsp;} while (res != FR_OK);
&nbsp;&nbsp;
&nbsp;&nbsp;//nb files
&nbsp;&nbsp;for (;;) {
&nbsp;&nbsp;&nbsp;&nbsp;res = pf_readdir(&amp;dir, &amp;fno);
&nbsp;&nbsp;&nbsp;&nbsp;if (res != FR_OK || fno.fname[0] == 0) break;
&nbsp;&nbsp;&nbsp;&nbsp;wdt_reset();
&nbsp;&nbsp;&nbsp;&nbsp;nbwave++;
&nbsp;&nbsp;&nbsp;&nbsp;seednumber++;
&nbsp;&nbsp;}
&nbsp;&nbsp;
&nbsp;&nbsp;srandom(seednumber);
&nbsp;&nbsp;//start with a random position
&nbsp;&nbsp;position = rangerandom(1, nbwave + 1);

&nbsp;&nbsp;for (;;) {
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;//limit
&nbsp;&nbsp;&nbsp;&nbsp;if(position &gt; (nbwave + 1)) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;position = 1;
&nbsp;&nbsp;&nbsp;&nbsp;} else if(position &lt; 1) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;position = 1;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;//play
&nbsp;&nbsp;&nbsp;&nbsp;sprintf(strbuff,&quot;%d.wav&quot;, position);
&nbsp;&nbsp;&nbsp;&nbsp;play(strbuff);
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;//increment song
&nbsp;&nbsp;&nbsp;&nbsp;position++;

&nbsp;&nbsp;}
}
</pre></pre></p>
<p>servo source code</p>
<p><pre><pre class="brush:c">
#include &lt;avr/io.h&gt;
#include &lt;avr/interrupt.h&gt;
#include &lt;inttypes.h&gt;
#include &lt;avr/sleep.h&gt;
#include &lt;util/delay.h&gt; 

#define F_CPU 8000000
#define nop()&nbsp;&nbsp;__asm__ __volatile__(&quot;nop&quot;)

void wait100us(void) {
&nbsp;&nbsp;&nbsp;&nbsp;unsigned char i;
&nbsp;&nbsp;&nbsp;&nbsp;for(i = 0; i &lt; 100; i++) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nop();
&nbsp;&nbsp;&nbsp;&nbsp;}
}

void Delay_ms(unsigned int t)

&nbsp;&nbsp;{
&nbsp;&nbsp; unsigned int i, aika;
&nbsp;&nbsp; aika = 140;

&nbsp;&nbsp; while(t--)
&nbsp;&nbsp;&nbsp;&nbsp;for(i = 0; i &lt; aika; i++)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(t==0) return;

&nbsp;&nbsp;} 

void adcinit (void) {

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// PRESCALER 128
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ADCSRA |= (1 &lt;&lt; ADPS2) | (1 &lt;&lt; ADPS1) | (0 &lt;&lt; ADPS0);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// AUTO TRIGGER ENABLE
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ADCSRA |= (1 &lt;&lt; ADATE);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// VCC ref
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ADMUX |= (0 &lt;&lt; REFS1) | (0 &lt;&lt; REFS0);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// RIGHT ADJUST
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ADCSRB |= (0 &lt;&lt; ADLAR);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// CHANNEL 0
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ADMUX |= (0 &lt;&lt; MUX5) | (0 &lt;&lt; MUX4) | (0 &lt;&lt; MUX3) | (0 &lt;&lt; MUX2) | (0 &lt;&lt; MUX1) | (1 &lt;&lt; MUX0);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// FREE RUNNING MODE
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ADCSRB |= (0 &lt;&lt; ADTS2) | (0 &lt;&lt; ADTS1) | (0 &lt;&lt; ADTS0);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// ENABLE ADC
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ADCSRA |= (1 &lt;&lt; ADEN);

&nbsp;&nbsp;&nbsp;&nbsp;// PORT A: INPUT
&nbsp;&nbsp;&nbsp;&nbsp;DDRA = 0x00;
&nbsp;&nbsp;&nbsp;&nbsp;PORTA = 0x00;

}

void pwminit (void) {
&nbsp;&nbsp;&nbsp;&nbsp;// disable PWM while configuring it
&nbsp;&nbsp;&nbsp;&nbsp;TCCR1A = 0;

&nbsp;&nbsp;&nbsp;&nbsp;// used for TOP, makes for 50 hz PWM = (8,000,000 / (8 * 50)) - 1
&nbsp;&nbsp;&nbsp;&nbsp;ICR1 = 19999;

&nbsp;&nbsp;&nbsp;&nbsp;// servo pins outputs
&nbsp;&nbsp;&nbsp;&nbsp;DDRA = _BV(PA5) | _BV(PA6);

&nbsp;&nbsp;&nbsp;&nbsp;// set up counter 1 (16 bit) to act as a dual channel PWM generator
&nbsp;&nbsp;&nbsp;&nbsp;// comparator mode = non-inverting, use ICR1 as TOP and have a prescale of 8.
&nbsp;&nbsp;&nbsp;&nbsp;TCCR1A = _BV(COM1A1) | _BV(COM1B1) | _BV(WGM11);
&nbsp;&nbsp;&nbsp;&nbsp;TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS11);
}

long map(long x, long in_min, long in_max, long out_min, long out_max)
{
&nbsp;&nbsp;return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

int main() {

&nbsp;&nbsp;adcinit();
&nbsp;&nbsp;pwminit();
&nbsp;&nbsp;&nbsp;&nbsp;sei();

&nbsp;&nbsp;&nbsp;&nbsp;// START A2D
&nbsp;&nbsp;&nbsp;&nbsp;ADCSRA |= (1 &lt;&lt; ADSC);

&nbsp;&nbsp;while(1) {
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;//700 to 2400
&nbsp;&nbsp;&nbsp;&nbsp;//but here we need only 50 degress
&nbsp;&nbsp;&nbsp;&nbsp;OCR1A = map(ADC, 0, 1023, 700, 1100);
&nbsp;&nbsp;&nbsp;&nbsp;ADMUX |= (1 &lt;&lt; MUX1);
&nbsp;&nbsp;&nbsp;&nbsp;ADMUX &amp;= ~(1 &lt;&lt; MUX0);
&nbsp;&nbsp;&nbsp;&nbsp;Delay_ms(2);
&nbsp;&nbsp;&nbsp;&nbsp;OCR1B = map(ADC, 0, 1023, 700, 1100);
&nbsp;&nbsp;&nbsp;&nbsp;ADMUX |= (1 &lt;&lt; MUX0);
&nbsp;&nbsp;&nbsp;&nbsp;ADMUX &amp;= ~(1 &lt;&lt; MUX1);
&nbsp;&nbsp;&nbsp;&nbsp;Delay_ms(2);
&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;return(0);
}
</pre></pre></p>
]]></content:encoded>
			<wfw:commentRss>http://www.workinprogress.ca/singing-birds/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>biscuit box computer</title>
		<link>http://www.workinprogress.ca/biscuit-box-computer/</link>
		<comments>http://www.workinprogress.ca/biscuit-box-computer/#comments</comments>
		<pubDate>Thu, 01 Apr 2010 23:06:04 +0000</pubDate>
		<dc:creator>psc</dc:creator>
				<category><![CDATA[Electronics]]></category>

		<guid isPermaLink="false">http://www.workinprogress.ca/?p=674</guid>
		<description><![CDATA[i am sure there&#8217;s plenty of projects like this one. the idea is to get a &#8220;cheap&#8221; and &#8220;small&#8221; full featured linux box. a good keyword to start with: itx motherboard cpu combo. this one have hdmi 1080p, wifi, dual-core 1.6 ghz. i paid 147$ used. got also 1 gig of used ram for 20$. [...]]]></description>
			<content:encoded><![CDATA[<p>i am sure there&#8217;s plenty of projects like this one. the idea is to get a &#8220;cheap&#8221; and &#8220;small&#8221; full featured linux box. a good keyword to start with: itx motherboard cpu combo. this one have hdmi 1080p, wifi, dual-core 1.6 ghz. i paid 147$ used. got also 1 gig of used ram for 20$. total of 167$ CAD. weight is 0.8 kg for the box and 0.3 kg for the supply. Just 18W at idle, and 23W full load (someone measured it with a Kill-a-watt device). the power supply is 90W. for the storage, i went with a laptop hard-drive (it&#8217;s smaller). i paid 100$ for a 500 gig, 7200 rpm, sata.</p>
<p>all this information will be outdated, now.</p>

<a href='http://www.workinprogress.ca/biscuit-box-computer/p4020066/' title='P4020066'><img width="150" height="150" src="http://www.workinprogress.ca/wp-content/uploads/P4020066-150x150.jpg" class="attachment-thumbnail" alt="P4020066" title="P4020066" /></a>
<a href='http://www.workinprogress.ca/biscuit-box-computer/p4020069/' title='itx motherboard cpu combo with the external supply'><img width="150" height="150" src="http://www.workinprogress.ca/wp-content/uploads/P4020069-150x150.jpg" class="attachment-thumbnail" alt="itx motherboard cpu combo with the external supply" title="itx motherboard cpu combo with the external supply" /></a>
<a href='http://www.workinprogress.ca/biscuit-box-computer/p4020072/' title='P4020072'><img width="150" height="150" src="http://www.workinprogress.ca/wp-content/uploads/P4020072-150x150.jpg" class="attachment-thumbnail" alt="P4020072" title="P4020072" /></a>
<a href='http://www.workinprogress.ca/biscuit-box-computer/p4020073/' title='P4020073'><img width="150" height="150" src="http://www.workinprogress.ca/wp-content/uploads/P4020073-150x150.jpg" class="attachment-thumbnail" alt="P4020073" title="P4020073" /></a>
<a href='http://www.workinprogress.ca/biscuit-box-computer/p4020074/' title='P4020074'><img width="150" height="150" src="http://www.workinprogress.ca/wp-content/uploads/P4020074-150x150.jpg" class="attachment-thumbnail" alt="P4020074" title="P4020074" /></a>
<a href='http://www.workinprogress.ca/biscuit-box-computer/p4300098/' title='laptop hard-drive fixed on top'><img width="150" height="150" src="http://www.workinprogress.ca/wp-content/uploads/P4300098-150x150.jpg" class="attachment-thumbnail" alt="laptop hard-drive fixed on top" title="laptop hard-drive fixed on top" /></a>

<p>running a realtime kernel with enlightenment and blender:</p>
<p><object width="400" height="320"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=11384664&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=00ADEF&amp;fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=11384664&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=00ADEF&amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="320"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://www.workinprogress.ca/biscuit-box-computer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>kicad &#8211; video tutorial</title>
		<link>http://www.workinprogress.ca/kicad-video-tutorial/</link>
		<comments>http://www.workinprogress.ca/kicad-video-tutorial/#comments</comments>
		<pubDate>Sun, 24 Jan 2010 07:49:01 +0000</pubDate>
		<dc:creator>psc</dc:creator>
				<category><![CDATA[Electronics]]></category>

		<guid isPermaLink="false">http://www.workinprogress.ca/?p=622</guid>
		<description><![CDATA[Kicad is an open source (GPL) software for the creation of electronic schematic diagrams and printed circuit board artwork. schematic editor &#38; cvpcb (transcript): pcbnew (transcript): V-USB kicad project (clean): http://www.workinprogress.ca/wp-content/uploads/kicad_vusb.zip Kicad: http://kicad.sourceforge.net/wiki/index.php/Main_Page Update: http://kicad.1301.cz/ Libraries: http://kicadlib.org/ http://per.launay.free.fr/kicad/kicad_php/composant.php Tutorial: http://KiCadHowTo.org]]></description>
			<content:encoded><![CDATA[<p><strong>Kicad</strong> is an open source (GPL) software for the creation of electronic schematic diagrams and printed circuit board artwork.</p>
<p>schematic editor &amp; cvpcb (<a href="http://www.workinprogress.ca/wp-content/uploads/eeschema.txt">transcript</a>):</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="540" height="405" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/rkQ0nVX1q1k&amp;hl=en_US&amp;fs=1&amp;rel=0&amp;hd=1" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="540" height="405" src="http://www.youtube.com/v/rkQ0nVX1q1k&amp;hl=en_US&amp;fs=1&amp;rel=0&amp;hd=1" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p>pcbnew (<a href="http://www.workinprogress.ca/wp-content/uploads/pcbnew.txt">transcript</a>):</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="540" height="405" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/8HNMihqa844&amp;hl=en_US&amp;fs=1&amp;rel=0&amp;hd=1" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="540" height="405" src="http://www.youtube.com/v/8HNMihqa844&amp;hl=en_US&amp;fs=1&amp;rel=0&amp;hd=1" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p>V-USB kicad project (clean):<br />
<a href="http://www.workinprogress.ca/wp-content/uploads/kicad_vusb.zip">http://www.workinprogress.ca/wp-content/uploads/kicad_vusb.zip</a></p>
<p>Kicad:<br />
<a href="http://kicad.sourceforge.net/wiki/index.php/Main_Page">http://kicad.sourceforge.net/wiki/index.php/Main_Page</a></p>
<p>Update:<br />
<a href="http://kicad.1301.cz/">http://kicad.1301.cz/</a></p>
<p>Libraries:<br />
<a href="http://kicadlib.org/">http://kicadlib.org/</a><br />
<a href="http://per.launay.free.fr/kicad/kicad_php/composant.php">http://per.launay.free.fr/kicad/kicad_php/composant.php</a></p>
<p>Tutorial:<br />
<a href="http://KiCadHowTo.org">http://KiCadHowTo.org</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.workinprogress.ca/kicad-video-tutorial/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>filtering pwm for music</title>
		<link>http://www.workinprogress.ca/filtering-pwm-for-music/</link>
		<comments>http://www.workinprogress.ca/filtering-pwm-for-music/#comments</comments>
		<pubDate>Sun, 29 Nov 2009 06:37:58 +0000</pubDate>
		<dc:creator>psc</dc:creator>
				<category><![CDATA[Electronics]]></category>

		<guid isPermaLink="false">http://www.workinprogress.ca/?p=581</guid>
		<description><![CDATA[i would like to start by saying that this solution might not be the best&#8230; if any analog guru read this, please leave a comment. for 2.75$ you can have a chip that is able to run at 64 mhz (phase-locked loop) and output a pulse width modulation at 250 khz. attiny85 is your friend [...]]]></description>
			<content:encoded><![CDATA[<p><em>i would like to start by saying that this solution might not be the best&#8230; if any analog guru read this, please leave a comment.</em></p>
<p>for 2.75$ you can have a chip that is able to run at 64 mhz (phase-locked loop) and output a pulse width modulation at 250 khz. attiny85 is your friend here. i didn&#8217;t found any atmega with this option (pll)&#8230; the good news is that it&#8217;s fast enough to output a stereo WAV at 16 bits / 48 khz. if you are interested in this project, take a look here: <a href="http://elm-chan.org/works/sd8p/report.html" target="_blank">http://elm-chan.org/works/sd8p/report.html</a></p>
<p>since i want to connect the pwm output in a power amplifier, i need to filter the signal. here&#8217;s the waveform of the pulse width modulation @ 440 hz:</p>
<p><a href="http://www.workinprogress.ca/wp-content/uploads/pwm_signal.jpg"><img class="alignnone size-medium wp-image-587" title="pwm_signal" src="http://www.workinprogress.ca/wp-content/uploads/pwm_signal-300x242.jpg" alt="pwm_signal" width="300" height="242" /></a></p>
<p>now let&#8217;s see if we use a simple <a href="http://en.wikipedia.org/wiki/Low-pass_filter#Passive_electronic_realization" target="_blank">RC low pass</a>:</p>
<p><a href="http://www.workinprogress.ca/wp-content/uploads/pwm_filtered_rc_osc.jpg"><img class="alignnone size-medium wp-image-589" title="pwm_filtered_rc_osc" src="http://www.workinprogress.ca/wp-content/uploads/pwm_filtered_rc_osc-300x241.jpg" alt="pwm_filtered_rc_osc" width="300" height="241" /></a></p>
<p>looks good to me, but then testing with a triangle instead of an oscillator revealed this:</p>
<p><a href="http://www.workinprogress.ca/wp-content/uploads/pwm_filtered_rc_tri.jpg"><img class="alignnone size-medium wp-image-590" title="pwm_filtered_rc_tri" src="http://www.workinprogress.ca/wp-content/uploads/pwm_filtered_rc_tri-300x242.jpg" alt="pwm_filtered_rc_tri" width="300" height="242" /></a></p>
<p>that&#8217;s not beautiful&#8230; here&#8217;s a close-up:</p>
<p><a href="http://www.workinprogress.ca/wp-content/uploads/pwm_filtered_closeup_rc.jpg"><img class="alignnone size-medium wp-image-592" title="pwm_filtered_closeup_rc" src="http://www.workinprogress.ca/wp-content/uploads/pwm_filtered_closeup_rc-300x240.jpg" alt="pwm_filtered_closeup_rc" width="300" height="240" /></a></p>
<p>maybe using more passive filter could help, but since you need to use an op-amp as a buffer (so that your load doesn&#8217;t affect the RC filter), why not use a <a href="http://en.wikipedia.org/wiki/Sallen%E2%80%93Key_topology#Example:_Low-pass_filter" target="_blank">sallen-key topology</a>. this will act as an active low pass filter and a buffer. let&#8217;s look at the results:</p>
<p><a href="http://www.workinprogress.ca/wp-content/uploads/pwm_filtered_sk_tri.jpg"><img class="alignnone size-medium wp-image-594" title="pwm_filtered_sk_tri" src="http://www.workinprogress.ca/wp-content/uploads/pwm_filtered_sk_tri-300x240.jpg" alt="pwm_filtered_sk_tri" width="300" height="240" /></a></p>
<p>close-up:</p>
<p><a href="http://www.workinprogress.ca/wp-content/uploads/pwm_filtered_closeup_sk.jpg"><img class="alignnone size-medium wp-image-595" title="pwm_filtered_closeup_sk" src="http://www.workinprogress.ca/wp-content/uploads/pwm_filtered_closeup_sk-300x240.jpg" alt="pwm_filtered_closeup_sk" width="300" height="240" /></a></p>
<p>not perfect, but better!</p>
<p><strong>SIMULATIONS<br />
<span style="font-weight: normal;">simple RC (250khz = -22db)<br />
<a href="http://www.workinprogress.ca/wp-content/uploads/rc.jpg"><img class="alignnone size-full wp-image-608" title="rc" src="http://www.workinprogress.ca/wp-content/uploads/rc.jpg" alt="" width="331" height="309" /></a></span></strong></p>
<p>sallen-key second-order (250khz = -44db)<br />
<a href="http://www.workinprogress.ca/wp-content/uploads/skso.jpg"><img class="alignnone size-full wp-image-609" title="skso" src="http://www.workinprogress.ca/wp-content/uploads/skso.jpg" alt="" width="339" height="306" /></a></p>
<p>sallen-key third-order (250khz = -67db)<br />
<a href="http://www.workinprogress.ca/wp-content/uploads/skto.jpg"><img class="alignnone size-full wp-image-610" title="skto" src="http://www.workinprogress.ca/wp-content/uploads/skto.jpg" alt="" width="347" height="306" /></a></p>
<p>third-order is the best and using <a href="http://www.beis.de/Elektronik/Filter/Act3PoleLP.html" target="_blank">this method</a> only 1 stage is needed.</p>
<p>when choosing the op-amp, consider this:<br />
100 * highest Q * GBW = Gain Bandwidth Product (read about it <a href="http://www.beis.de/Elektronik/Filter/Filter.html" target="_blank">here</a>)<a title="Volt" href="http://en.wikipedia.org/wiki/Volt"><br />
</a>slew rate =&gt; 2V/µs<br />
i am using a rail-to-rail input / output op-amp.</p>
<p>now simply add an electrolytic capacitor (100 uf) and you can feed an amplifier with the original pwm signal (hopefully).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.workinprogress.ca/filtering-pwm-for-music/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>V-USB tutorial (software-only usb for mega &amp; tiny)</title>
		<link>http://www.workinprogress.ca/v-usb-tutorial-software-only-usb-for-mega-tiny/</link>
		<comments>http://www.workinprogress.ca/v-usb-tutorial-software-only-usb-for-mega-tiny/#comments</comments>
		<pubDate>Sun, 30 Aug 2009 23:31:07 +0000</pubDate>
		<dc:creator>psc</dc:creator>
				<category><![CDATA[Electronics]]></category>

		<guid isPermaLink="false">http://www.workinprogress.ca/?p=430</guid>
		<description><![CDATA[Arduino use the FTDI chip for usb communication (not anymore). This chip is expensive and only surface mount. To save money and be able to make a PCB at home, i found a software-only implementation of USB for AVR (attiny, atmega): http://www.obdev.at/products/vusb/index.html. You don&#8217;t need the 2 LEDs (visual feedback for debugging / bootloader). Not [...]]]></description>
			<content:encoded><![CDATA[<p>Arduino use the FTDI chip for usb communication (not anymore). This chip is expensive and only surface mount. To save money and be able to make a PCB at home, i found a software-only implementation of USB for AVR (attiny, atmega): <a href="http://www.obdev.at/products/vusb/index.html">http://www.obdev.at/products/vusb/index.html</a>.</p>
<p><a href="http://www.workinprogress.ca/wp-content/uploads/vusb_schematic.jpg"><img class="alignnone size-medium wp-image-487" title="vusb_schematic" src="http://www.workinprogress.ca/wp-content/uploads/vusb_schematic-300x225.jpg" alt="vusb_schematic" width="300" height="225" /></a></p>
<p>
<em>You don&#8217;t need the 2 LEDs (visual feedback for debugging / bootloader).<br />
Not using a bootloader? Then you can connect R4 to VCC (thus freeing PD4).</em>
</p>
<p><a href="http://www.workinprogress.ca/wp-content/uploads/vusb_breadboard.jpg"><img class="alignnone size-medium wp-image-473" title="vusb_breadboard" src="http://www.workinprogress.ca/wp-content/uploads/vusb_breadboard-300x147.jpg" alt="vusb_breadboard" width="300" height="147" /></a></p>
<p><span style="color: #800000;">I am using an ATMEGA164p. The example code need to be modify to suit your device (bootloader address, registers, EEPROM functions).</span></p>
<p><em>This tutorial is for people who have some experience or are patient. Please pardon my english.</em></p>
<p><strong>1)</strong> <strong>breadboard</strong> your avr for programmation (SPI / JTAG)</p>
<p><strong>2)</strong> download <strong>vusb</strong> (<a href="http://www.obdev.at/products/vusb/download.html" target="_blank">last version</a>)</p>
<hr />
<p><strong>A SIMPLE TEST (hid mouse)</strong></p>
<p>cd vusb-x/examples/hid-mouse/firmware<br />
open <strong>usbconfig.h</strong> – set the pin for usb (USB_CFG_DMINUS_BIT – USB_CFG_DPLUS_BIT)<br />
open <strong>Makefile</strong> – edit DEVICE / F_CPU / FUSES / AVRDUDE<br />
make hex<br />
make program</p>
<p>Replug the device and automagically the mouse will move on your screen.</p>
<hr />
<p><strong>BOOTLOADERHID</strong><em> (optional)</em><br />
<strong>3)</strong> download <strong>bootloadhid</strong> (<a href="http://www.obdev.at/products/vusb/bootloadhid.html" target="_blank">last version</a>)<br />
This bootloader doesn&#8217;t require a driver (it&#8217;s HID). With it, you will be able to program your firmware without your programmer.</p>
<p><strong>4)</strong> <strong>delete</strong> usbdrv, <strong>cp</strong> the usbdrv from vusb<br />
<strong>5)</strong> open <strong>usbconfig.h</strong> &#8211; change the VENDOR and DEVICE name if you want<br />
<strong>6)</strong> open <strong>bootloaderconfig.h</strong> &#8211; set the pin for usb (USB_CFG_DMINUS_BIT &#8211; USB_CFG_DPLUS_BIT) and if you want to be able to reset via usb (USB_CFG_PULLUP_IOPORTNAME). Change the bootloadcondition to suit your needs, i am using the EEPROM to write (from the firmware) &#038; read (from the bootloader) + a button on PD5 (need to be hold) for the condition and finally 2 leds (so i know that i am in the bootloader).</p>
<p><a href="javascript:void(null);" onclick="s_toggleDisplay(document.getElementById('SID602708404'), this, 'show code &#9660;', 'hide code &#9650;');">show code &#9660;</a></p>
<div id='SID602708404' style='display:none;'>
<p><pre><pre class="brush:c">#define JUMPER_BIT&nbsp;&nbsp;5
#define BOOTLED_BIT&nbsp;&nbsp;6
#define BOOTLED_BITB&nbsp;&nbsp;7

static inline void&nbsp;&nbsp;bootLoaderInit(void)
{
&nbsp;&nbsp;DDRD |= (1 &lt;&lt; BOOTLED_BIT);&nbsp;&nbsp;&nbsp;&nbsp; // turn bootloader led on
&nbsp;&nbsp;DDRD |= (1 &lt;&lt; BOOTLED_BITB);&nbsp;&nbsp;&nbsp;&nbsp; // turn bootloader led on 2
&nbsp;&nbsp;PORTD |= (1 &lt;&lt; JUMPER_BIT);&nbsp;&nbsp;&nbsp;&nbsp; /* activate pull-up */
&nbsp;&nbsp;_delay_us(10);&nbsp;&nbsp;/* wait for levels to stabilize */
}

static inline void&nbsp;&nbsp;bootLoaderExit(void)
{
&nbsp;&nbsp;&nbsp;&nbsp;PORTD = (1 &lt;&lt; BOOTLED_BIT);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // turn bootloader led off
&nbsp;&nbsp;&nbsp;&nbsp;PORTD = (1 &lt;&lt; BOOTLED_BITB);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // turn bootloader led off
}</pre></pre>
</p></div>
<p>
<strong>7)</strong> main.c: Edit your condition, mine looks like this:<br />
<a href="javascript:void(null);" onclick="s_toggleDisplay(document.getElementById('SID997363606'), this, 'show code &#9660;', 'hide code &#9650;');">show code &#9660;</a></p>
<div id='SID997363606' style='display:none;'>
<p><pre><pre class="brush:c">...
static void leaveBootloader()
{
 DBG1(0x01, 0, 0);
 bootLoaderExit();
 cli();
...
}
// ------------------------------------------------------------------------------
// - Write to EEPROM
// ------------------------------------------------------------------------------
void eepromWrite(unsigned int uiAddress, unsigned char ucData)
{
&nbsp;&nbsp;/* Wait for completion of previous write */
&nbsp;&nbsp;while(EECR &amp; (1&lt;&lt;EEPE));
&nbsp;&nbsp;/* Set up address and Data Registers */
&nbsp;&nbsp;EEAR = uiAddress;
&nbsp;&nbsp;EEDR = ucData;
&nbsp;&nbsp;cli();
&nbsp;&nbsp;/* Write logical one to EEMPE */
&nbsp;&nbsp;EECR |= (1&lt;&lt;EEMPE);
&nbsp;&nbsp;/* Start eeprom write by setting EEPE */
&nbsp;&nbsp;EECR |= (1&lt;&lt;EEPE);
&nbsp;&nbsp;sei();
}

// ------------------------------------------------------------------------------
// - Read EEPROM
// ------------------------------------------------------------------------------
unsigned char eepromRead(unsigned int uiAddress)
{
&nbsp;&nbsp;/* Wait for completion of previous write */
&nbsp;&nbsp;while(EECR &amp; (1&lt;&lt;EEPE));
&nbsp;&nbsp;/* Set up address register */
&nbsp;&nbsp;EEAR = uiAddress;
&nbsp;&nbsp;/* Start eeprom read by writing EERE */
&nbsp;&nbsp;EECR |= (1&lt;&lt;EERE);
&nbsp;&nbsp;/* Return data from Data Register */
&nbsp;&nbsp;return EEDR;
}

int main(void)
{
&nbsp;&nbsp;&nbsp;&nbsp;/* initialize hardware */
&nbsp;&nbsp;&nbsp;&nbsp;bootLoaderInit();
&nbsp;&nbsp;&nbsp;&nbsp;odDebugInit();
&nbsp;&nbsp;&nbsp;&nbsp;DBG1(0x00, 0, 0);
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;unsigned char do_boot_load;
&nbsp;&nbsp;unsigned char do_boot_load_via_eeprom;
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;do_boot_load = ~PIND &amp; (1 &lt;&lt; JUMPER_BIT);&nbsp;&nbsp;// see if jumper is set (= 0)
&nbsp;&nbsp;&nbsp;&nbsp;do_boot_load_via_eeprom = eepromRead(0); // bootloader bit in eeprom address 0
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;/* jump to application if jumper is set */
&nbsp;&nbsp;&nbsp;&nbsp;if(do_boot_load || do_boot_load_via_eeprom){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;eepromWrite(0, 0); // reset bit in eeprom
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PORTD &amp;= ~(1 &lt;&lt; BOOTLED_BIT);&nbsp;&nbsp;/// Light led
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PORTD &amp;= ~(1 &lt;&lt; BOOTLED_BITB);&nbsp;&nbsp;/// Light second led
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;uchar i = 0, j = 0;
#ifndef TEST_MODE
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GICR = (1 &lt;&lt; IVCE);&nbsp;&nbsp;/* enable change of interrupt vectors */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GICR = (1 &lt;&lt; IVSEL); /* move interrupts to boot flash section */
#endif
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;initForUsbConnectivity();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;do{ /* main event loop */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wdt_reset();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;usbPoll();
#if BOOTLOADER_CAN_EXIT
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(exitMainloop){
#if F_CPU == 12800000
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;&nbsp;&nbsp;/* memory is tight at 12.8 MHz, save exit delay below */
#endif
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(--i == 0){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(--j == 0)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
#endif
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}while(1);
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;leaveBootloader();
&nbsp;&nbsp;&nbsp;&nbsp;return 0;
}
</pre></pre>
</p></div>
<p>
<strong>8)</strong> edit the Makefile</p>
<p>You need to know the BOOTLOADER_ADDRESS of your device (<a href="http://hubbard.engr.scu.edu/embedded/avr/bootloader/index.html" target="_blank">learn</a> <a href="http://blog.schicks.net/wp-content/uploads/2009/09/bootloader_faq.pdf" target="_blank">more</a> about bootloader). Basically your datasheet will tell you the Start Bootloader section (look for Boot Size Configuration) in word address. You need to multiply it by 2 (the toolchain works on BYTE ADDRESS). For example, the atmega164p for 1024 words, the address is: 1C00 * 2 = 3800.</p>
<p>I am using a 20mhz clock, V-USB can be clocked with 12 Mhz, 15 MHz, 16 MHz or 20 MHz crystal or from a 12.8 MHz or 16.5 MHz internal RC oscillator.</p>
<p>Finally, you need to set the <a href="http://www.engbedded.com/fusecalc/" target="_blank">fuse correctly</a>:</p>
<ul>
<li>Boot Flash section size = <strong>1024 words</strong></li>
<li><strong>Uncheck </strong>Divide clock by 8 internally</li>
</ul>
<p><pre><pre class="brush:bash">DEVICE = atmega164p
BOOTLOADER_ADDRESS = 3800
F_CPU = 20000000
FUSEH = 0xd8
FUSEL = 0xff
PROGRAMMER = avrispmkII
PORT = usb
...

make fuse
make flash</pre></pre>
<p>Now that you have the bootloaderhid, let&#8217;s write a simple firmware to test it.</p>
<p>test.c</p>
<p><pre><pre class="brush:c">
#define F_CPU 20000000
#include &lt;avr/io.h&gt;
#include &lt;util/delay.h&gt;

int main(void) {

&nbsp;&nbsp;// Set Port B pins as all outputs
&nbsp;&nbsp;DDRB = 0xff;

&nbsp;&nbsp;while(1) {

&nbsp;&nbsp;&nbsp;&nbsp;PORTB = 0xFF;
&nbsp;&nbsp;&nbsp;&nbsp;_delay_ms(100);

&nbsp;&nbsp;&nbsp;&nbsp;PORTB = 0x00;
&nbsp;&nbsp;&nbsp;&nbsp;_delay_ms(200);

&nbsp;&nbsp;}

&nbsp;&nbsp;return 1;
}
</pre></pre>
<p>then:<br />
avr-gcc -mmcu=atmega164p -Os test.c<br />
avr-objcopy -j .text -j .data -O ihex a.out a.hex</p>
<p>cd bootloader/commandline<br />
edit main.c if you changed the VENDOR and PRODUCT string<br />
make</p>
<p>You need to connect the usb cable <strong>while holding</strong> the reset button. 2 LEDs should light up and you should see in dmesg something like:</p>
<p>[ 1727.956432] usb 3-2: new low speed USB device using uhci_hcd<br />
[ 1728.119279] usb 3-2: configuration #1 chosen from 1 choice<br />
[ 1728.142142] generic-usb 0003:16C0:05DF.000A: hiddev97,hidraw4: USB HID v1.01 Device [YOURVENDOR YOURPRODUCT] on usb-0000:00:1a.0-2/input0</p>
<p>Do:<br />
./bootloadHID -r a.hex</p>
<p><strong>FIRMWARE</strong></p>
<p>Now what you want in your custom firmware is a way to tell your device to go in the bootloader (so you don&#8217;t have to hold the reset button anymore). With this method in place, adding the reset button is optional, but recommanded (in case you break something in the firmware, you need a way to go back in the bootloader).</p>
<p>Remember, in the bootloader we are reading the EEPROM to see if we need to stay in the bootloader section, if not we load the firmware. So in the firmware we will write the EEPROM if we want to go in the bootloader.<br />
<a href="javascript:void(null);" onclick="s_toggleDisplay(document.getElementById('SID255654994'), this, 'show code &#9660;', 'hide code &#9650;');">show code &#9660;</a></p>
<div id='SID255654994' style='display:none;'>
<p><pre><pre class="brush:c">
// ------------------------------------------------------------------------------
// - Write to EEPROM
// ------------------------------------------------------------------------------
void eepromWrite(unsigned int uiAddress, unsigned char ucData) {
&nbsp;&nbsp;while(EECR &amp; (1&lt;&lt;EEPE));
&nbsp;&nbsp;EEAR = uiAddress;
&nbsp;&nbsp;EEDR = ucData;
&nbsp;&nbsp;cli();
&nbsp;&nbsp;EECR |= (1&lt;&lt;EEMPE);
&nbsp;&nbsp;EECR |= (1&lt;&lt;EEPE);
&nbsp;&nbsp;sei();
}

/* ------------------------------------------------------------------------- */
/* ------------------------------- BOOTLOADER ------------------------------ */
/* ------------------------------------------------------------------------- */
void (*jump_to_bootloader)(void) = 0x1C00; __attribute__ ((unused))

void startBootloader(void) {
&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;eepromWrite(0 , 1);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// stay in bootloader
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;TIMSK0 &amp;= ~(1&lt;&lt;TOIE0);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// disable timer overflow
&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;cli();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// turn off interrupts
&nbsp;&nbsp;&nbsp;&nbsp;wdt_disable();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// disable watchdog timer
&nbsp;&nbsp;&nbsp;&nbsp;usbDeviceDisconnect();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // disconnect from USB bus
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;cbi(ADCSRA, ADIE);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// disable ADC interrupts
&nbsp;&nbsp;&nbsp;&nbsp;cbi(ADCSRA, ADEN);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// disable ADC (turn off ADC power)
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;PORTA = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// pull all pins low
&nbsp;&nbsp;&nbsp;&nbsp;PORTB = 0;
&nbsp;&nbsp;&nbsp;&nbsp;PORTC = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;jump_to_bootloader();
}

// - main
int main(void)
{

&nbsp;&nbsp;while(1) {

&nbsp;&nbsp;&nbsp;&nbsp;//jump to bootloader if jumper is HIGH
&nbsp;&nbsp;&nbsp;&nbsp;if(bit_is_clear(PIND, 5)) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;startBootloader();
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;}
&nbsp;&nbsp;return 0;
}</pre></pre>
</p></div>
<p>
You are ready to write the firmware for your application. Since you are using V-USB not only it let you upgrade your firmware very easily, but you can of course send and receive message between your computer and the device. Here&#8217;s an example of sending the value of a potentiometer to your computer and telling your device to blink a led at a certain speed. This example is for my device, Atmega164p.</p>
<p><a href="http://www.workinprogress.ca/wp-content/uploads/vusbtut.tar.gz"><strong>vusbtut.tar.gz</strong></a></p>
<p><strong>WINDOWS</strong><br />
You can trick Windows so it doesn&#8217;t popup the driver installation when you plug your device. Your need to use a HID descriptor (Vendor type requests sent to custom HID class device).</p>
<p>hiddescriptor.h<br />
<a href="javascript:void(null);" onclick="s_toggleDisplay(document.getElementById('SID417983528'), this, 'show code &#9660;', 'hide code &#9650;');">show code &#9660;</a></p>
<div id='SID417983528' style='display:none;'>
<p><pre><pre class="brush:c">// This HidReportDescriptor is not used, it&#039;s only here for avoiding a driver popup install on Windows
// See: Vendor type requests sent to custom HID class device
// http://vusb.wikidot.com/usb-device-classes

PROGMEM char usbHidReportDescriptor[33] = {
0x06, 0x00, 0xff,              // USAGE_PAGE (Generic Desktop)
0x09, 0x01,                    // USAGE (Vendor Usage 1)
0xa1, 0x01,                    // COLLECTION (Application)
0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
0x75, 0x08,                    //   REPORT_SIZE (8)

0x85, 0x01,                    //   REPORT_ID (1)
0x95, 0x06,                    //   REPORT_COUNT (6)
0x09, 0x00,                    //   USAGE (Undefined)
0xb2, 0x02, 0x01,              //   FEATURE (Data,Var,Abs,Buf)

0x85, 0x02,                    //   REPORT_ID (2)
0x95, 0x83,                    //   REPORT_COUNT (131)
0x09, 0x00,                    //   USAGE (Undefined)
0xb2, 0x02, 0x01,              //   FEATURE (Data,Var,Abs,Buf)
0xc0                           // END_COLLECTION
};</pre></pre>
</p></div>
<p>
usbconfig.h<br />
<a href="javascript:void(null);" onclick="s_toggleDisplay(document.getElementById('SID1836011153'), this, 'show code &#9660;', 'hide code &#9650;');">show code &#9660;</a></p>
<div id='SID1836011153' style='display:none;'>
<p><pre><pre class="brush:c">#define USB_CFG_DEVICE_CLASS        0    /* set to 0 if deferred to interface */
#define USB_CFG_DEVICE_SUBCLASS     0
/* See USB specification if you want to conform to an existing device class.
* Class 0xff is &quot;vendor specific&quot;.
*/
#define USB_CFG_INTERFACE_CLASS     0x03   /* define class here if not at device level */
#define USB_CFG_INTERFACE_SUBCLASS  0
#define USB_CFG_INTERFACE_PROTOCOL  0
/* See USB specification if you want to conform to an existing device class or
* protocol. The following classes must be set at interface level:
* HID class is 3, no subclass and protocol required (but may be useful!)
* CDC class is 2, use subclass 2 and protocol 1 for ACM
*/
#define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH    33</pre></pre>
<p>main.c</p>
<p><pre><pre class="brush:c">
#include &lt;avr/io.h&gt;
#include &lt;avr/interrupt.h&gt;
#include &lt;avr/pgmspace.h&gt;
#include &lt;avr/wdt.h&gt;
#include &quot;usbdrv.h&quot;
#include &quot;hiddescriptor.h&quot;
</pre></pre>
</p></div>
<p>
Here&#8217;s an example for installing the software &amp; driver:<br />
<a href="http://www.workinprogress.ca/wp-content/uploads/edubeat.zip"><strong>edubeat.zip</strong></a></p>
<p><strong>HOST SOFTWARE<br />
</strong></p>
<p>Here&#8217;s the most basic host software written in python.<br />
<a href="javascript:void(null);" onclick="s_toggleDisplay(document.getElementById('SID2071682423'), this, 'show code &#9660;', 'hide code &#9650;');">show code &#9660;</a></p>
<div id='SID2071682423' style='display:none;'>
<p><pre><pre class="brush:python">
import usb

def findDevice(vendor_id):
&nbsp;&nbsp;buses = usb.busses()
&nbsp;&nbsp;for bus in buses :
&nbsp;&nbsp;&nbsp;&nbsp;for device in bus.devices :
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print &#039;idVendor: %x&#039; % device.idVendor
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if device.idVendor == vendor_id:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print &#039;Found&#039;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return device
&nbsp;&nbsp;return None

class VUSB:
&nbsp;&nbsp;USB_VENDOR_ID = 0x16C0
&nbsp;&nbsp;REQUEST_TYPE = usb.TYPE_VENDOR | usb.RECIP_DEVICE | usb.ENDPOINT_IN

&nbsp;&nbsp;USB_BUFFER_SIZE = 2
&nbsp;&nbsp;CMD_ZERO = 0

&nbsp;&nbsp;def __init__(self):
&nbsp;&nbsp;&nbsp;&nbsp;device = findDevice(self.USB_VENDOR_ID)
&nbsp;&nbsp;&nbsp;&nbsp;if not device:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise Exception(&#039;Device not available&#039;)
&nbsp;&nbsp;&nbsp;&nbsp;self.handle = device.open()

&nbsp;&nbsp;def getBufferSize(self):
&nbsp;&nbsp;&nbsp;&nbsp;return self.send_cmd(self.CMD_ZERO)

&nbsp;&nbsp;def send_cmd(self, cmd, param=0):
&nbsp;&nbsp;&nbsp;&nbsp;val = self.handle.controlMsg(requestType = self.REQUEST_TYPE, request = cmd, value = param, buffer = self.USB_BUFFER_SIZE)
&nbsp;&nbsp;&nbsp;&nbsp;return val

def main():
&nbsp;&nbsp;client = VUSB()
&nbsp;&nbsp;print client.getBufferSize()

if __name__ == &#039;__main__&#039;:
&nbsp;&nbsp;main()
</pre></pre>
</p></div>
<p>
<strong>HARDWARE</strong></p>
<p>V-USB runs on any AVR microcontroller with at least 2 kB of Flash memory, 128 bytes RAM and a clock rate of at least 12 MHz. For example the ATTINY25 can do the job. The price of this chip is <del datetime="2010-10-01T02:25:10+00:00">1.66</del> 2.00 USD!</p>
<p><strong>TEMPLATE</strong></p>
<p>Here&#8217;s my template for the Atmega164p. This firmware is ready for ADC free-running mode, SPI master (you need to +5V PB4), external interrupts (PORTC), EEPROM read / write, jump to bootloader.<br />
<a href="javascript:void(null);" onclick="s_toggleDisplay(document.getElementById('SID1658696883'), this, 'show code &#9660;', 'hide code &#9650;');">show code &#9660;</a></p>
<div id='SID1658696883' style='display:none;'>
<p><pre><pre class="brush:c">
#include &lt;avr/io.h&gt;
#include &lt;avr/interrupt.h&gt;
#include &lt;avr/pgmspace.h&gt;
#include &lt;avr/wdt.h&gt;
#include &lt;util/delay.h&gt;

#include &quot;usbdrv.h&quot;
#include &quot;hiddescriptor.h&quot;
#include &quot;utils.h&quot;

// - Define
#define DD_MOSI&nbsp;&nbsp;&nbsp;&nbsp; PINB5
#define DD_SCK&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PINB7
#define ADC_PINS 8

// - Global
static uint8_t usb_reply[10];

// - Write to EEPROM
void eepromWrite(unsigned int uiAddress, unsigned char ucData) {
&nbsp;&nbsp;while(EECR &amp; (1&lt;&lt;EEPE));
&nbsp;&nbsp;EEAR = uiAddress;
&nbsp;&nbsp;EEDR = ucData;
&nbsp;&nbsp;cli();
&nbsp;&nbsp;EECR |= (1&lt;&lt;EEMPE);
&nbsp;&nbsp;EECR |= (1&lt;&lt;EEPE);
&nbsp;&nbsp;sei();
}

// - Read EEPROM
unsigned char eepromRead(unsigned int uiAddress) {
&nbsp;&nbsp;while(EECR &amp; (1&lt;&lt;EEPE));
&nbsp;&nbsp;EEAR = uiAddress;
&nbsp;&nbsp;EECR |= (1&lt;&lt;EERE);
&nbsp;&nbsp;return EEDR;
}

// - Bootloader
void (*jump_to_bootloader)(void) = 0x1C00; __attribute__ ((unused))

void startBootloader(void) {
&nbsp;&nbsp;eepromWrite(0, 1);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// stay in bootloader
&nbsp;&nbsp;TIMSK0 &amp;= ~(1&lt;&lt;TOIE0);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// disable timer overflow
&nbsp;&nbsp;cli();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// turn off interrupts
&nbsp;&nbsp;wdt_disable();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// disable watchdog timer
&nbsp;&nbsp;usbDeviceDisconnect();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // disconnect from USB bus
&nbsp;&nbsp;cbi(ADCSRA, ADIE);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// disable ADC interrupts
&nbsp;&nbsp;cbi(ADCSRA, ADEN);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// disable ADC (turn off ADC power)
&nbsp;&nbsp;jump_to_bootloader();
}

// - usbFunctionSetup
USB_PUBLIC uchar usbFunctionSetup(uchar data[8]) {
&nbsp;&nbsp;usbRequest_t&nbsp;&nbsp;&nbsp;&nbsp;*rq = (void *)data;
&nbsp;&nbsp;static uchar&nbsp;&nbsp;&nbsp;&nbsp;replyBuf[10];

&nbsp;&nbsp;usbMsgPtr = replyBuf;
&nbsp;&nbsp;if(rq-&gt;bRequest == 0) { //POST

&nbsp;&nbsp;&nbsp;&nbsp;replyBuf[0] = usb_reply[0];
&nbsp;&nbsp;&nbsp;&nbsp;replyBuf[1] = usb_reply[1];
&nbsp;&nbsp;&nbsp;&nbsp;replyBuf[2] = usb_reply[2];
&nbsp;&nbsp;&nbsp;&nbsp;replyBuf[3] = usb_reply[3];
&nbsp;&nbsp;&nbsp;&nbsp;replyBuf[4] = usb_reply[4];
&nbsp;&nbsp;&nbsp;&nbsp;replyBuf[5] = usb_reply[5];
&nbsp;&nbsp;&nbsp;&nbsp;replyBuf[6] = usb_reply[6];
&nbsp;&nbsp;&nbsp;&nbsp;replyBuf[7] = usb_reply[7];
&nbsp;&nbsp;&nbsp;&nbsp;replyBuf[8] = usb_reply[8];
&nbsp;&nbsp;&nbsp;&nbsp;replyBuf[9] = usb_reply[9];
&nbsp;&nbsp;&nbsp;&nbsp;return 10;

&nbsp;&nbsp;} else if(rq-&gt;bRequest == 1) { //GET
&nbsp;&nbsp;&nbsp;&nbsp;//rq-&gt;wIndex.bytes[0];
&nbsp;&nbsp;&nbsp;&nbsp;//rq-&gt;wValue.bytes[0];
&nbsp;&nbsp;}
&nbsp;&nbsp;return 0;
}

// - InterruptInit
void InterruptInit() {
&nbsp;&nbsp;PCICR |= (1 &lt;&lt; PCIE2);
&nbsp;&nbsp;PCMSK2 |= (1 &lt;&lt; PCINT23) | (1 &lt;&lt; PCINT22) | (1 &lt;&lt; PCINT21) | (1 &lt;&lt; PCINT20) | (1 &lt;&lt; PCINT19) | (1 &lt;&lt; PCINT18) | (1 &lt;&lt; PCINT17) | (1 &lt;&lt; PCINT16);
}

// - InterruptTrigged
SIGNAL (SIG_PIN_CHANGE2)
{
&nbsp;&nbsp;//CODE
}

// - SPI_MasterInit
void SPI_MasterInit(void) {
&nbsp;&nbsp;/* Set MOSI and SCK output, all others input */
&nbsp;&nbsp;DDRB = (1&lt;&lt;DD_MOSI)|(1&lt;&lt;DD_SCK);

&nbsp;&nbsp;/* Enable SPI, Master, set clock rate fck/16 */
&nbsp;&nbsp;SPCR = (1&lt;&lt;SPE)|(1&lt;&lt;MSTR);
&nbsp;&nbsp;SPSR = (1&lt;&lt;SPI2X);
}

// - SPI_MasterTransmit
void SPI_MasterTransmit(char cData) {
&nbsp;&nbsp;/* Start transmission */
&nbsp;&nbsp;SPDR = cData;
&nbsp;&nbsp;/* Wait for transmission complete */
&nbsp;&nbsp;while(!(SPSR &amp; (1&lt;&lt;SPIF)));
}

// - ADC_setPint
void ADC_setPin (int8_t pin) {
&nbsp;&nbsp;pin %= ADC_PINS;
&nbsp;&nbsp;pin&nbsp;&nbsp; |= ADMUX &amp; -8;
&nbsp;&nbsp;ADMUX&nbsp;&nbsp;= pin;
}

// - hardwareInit
static void hardwareInit(void)
{
&nbsp;&nbsp;//USB
&nbsp;&nbsp;uchar i, j;

&nbsp;&nbsp;/* activate pull-ups except on USB lines */
&nbsp;&nbsp;USB_CFG_IOPORT = (uchar) ~ ((1 &lt;&lt; USB_CFG_DMINUS_BIT) | (1 &lt;&lt; USB_CFG_DPLUS_BIT));

&nbsp;&nbsp;/* all pins input except USB (-&gt; USB reset) */
&nbsp;&nbsp;#ifdef USB_CFG_PULLUP_IOPORT&nbsp;&nbsp;&nbsp;&nbsp;/* use usbDeviceConnect()/usbDeviceDisconnect() if available */
&nbsp;&nbsp;&nbsp;&nbsp;USBDDR = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* we do RESET by deactivating pullup */
&nbsp;&nbsp;&nbsp;&nbsp;usbDeviceDisconnect();
&nbsp;&nbsp;#else
&nbsp;&nbsp;&nbsp;&nbsp;USBDDR = (1 &lt;&lt; USB_CFG_DMINUS_BIT) | (1 &lt;&lt; USB_CFG_DPLUS_BIT);
&nbsp;&nbsp;#endif

&nbsp;&nbsp;j = 0;
&nbsp;&nbsp;while (--j) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* USB Reset by device only required on Watchdog Reset */
&nbsp;&nbsp;&nbsp;&nbsp;i = 0;
&nbsp;&nbsp;&nbsp;&nbsp;while (--i);&nbsp;&nbsp;&nbsp;&nbsp;/* delay &gt;10ms for USB reset */
&nbsp;&nbsp;}

&nbsp;&nbsp;#ifdef USB_CFG_PULLUP_IOPORT
&nbsp;&nbsp;&nbsp;&nbsp;usbDeviceConnect();
&nbsp;&nbsp;#else
&nbsp;&nbsp;&nbsp;&nbsp;USBDDR = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;&nbsp;remove USB reset condition */
&nbsp;&nbsp;#endif

&nbsp;&nbsp;// ADC SETUP :: FREE RUNNING MODE

&nbsp;&nbsp;// PRESCALER 64
&nbsp;&nbsp;ADCSRA |= (1 &lt;&lt; ADPS2) | (1 &lt;&lt; ADPS1) | (0 &lt;&lt; ADPS0);
&nbsp;&nbsp;// AUTO TRIGGER ENABLE
&nbsp;&nbsp;ADCSRA |= (1 &lt;&lt; ADATE);
&nbsp;&nbsp;// AVCC with external capacitor at AREF pin
&nbsp;&nbsp;ADMUX |= (0 &lt;&lt; REFS1) | (1 &lt;&lt; REFS0);
&nbsp;&nbsp;// RIGHT ADJUST
&nbsp;&nbsp;ADMUX |= (0 &lt;&lt; ADLAR);
&nbsp;&nbsp;// CHANNEL 0
&nbsp;&nbsp;ADMUX |= (0 &lt;&lt; MUX4) | (0 &lt;&lt; MUX3) | (0 &lt;&lt; MUX2) | (0 &lt;&lt; MUX1) | (0 &lt;&lt; MUX0);
&nbsp;&nbsp;// FREE RUNNING MODE
&nbsp;&nbsp;ADCSRB |= (0 &lt;&lt; ADTS2) | (0 &lt;&lt; ADTS1) | (0 &lt;&lt; ADTS0);
&nbsp;&nbsp;// ENABLE ADC
&nbsp;&nbsp;ADCSRA |= (1 &lt;&lt; ADEN);

&nbsp;&nbsp;// PORT A: INPUT
&nbsp;&nbsp;DDRA = 0x00;
&nbsp;&nbsp;PORTA = 0x00;

&nbsp;&nbsp;// PORT B: OUTPUT
&nbsp;&nbsp;DDRB = 0xFF;

&nbsp;&nbsp;// PORT C: INPUT
&nbsp;&nbsp;DDRC = 0x00;

&nbsp;&nbsp;//POWER LED
&nbsp;&nbsp;DDRD |= (1 &lt;&lt; 6);
&nbsp;&nbsp;PORTD &amp;= ~(1 &lt;&lt; 6);

&nbsp;&nbsp;//SPI init
&nbsp;&nbsp;SPI_MasterInit();

&nbsp;&nbsp;//Interrupt init
&nbsp;&nbsp;InterruptInit();
}

// - Main
int main(void) {
&nbsp;&nbsp;wdt_enable(WDTO_1S);
&nbsp;&nbsp;hardwareInit();
&nbsp;&nbsp;usbInit();
&nbsp;&nbsp;sei();

&nbsp;&nbsp;ADCSRA |= (1 &lt;&lt; ADSC); //Start Free Running Mode

&nbsp;&nbsp;while(1) {
&nbsp;&nbsp;&nbsp;&nbsp;wdt_reset();
&nbsp;&nbsp;&nbsp;&nbsp;usbPoll();

&nbsp;&nbsp;&nbsp;&nbsp;//BOOTLOADER
&nbsp;&nbsp;&nbsp;&nbsp;if(bit_is_clear(PIND, 5)) {
&nbsp;&nbsp;&nbsp;&nbsp;startBootloader();
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;//SPI CODE
&nbsp;&nbsp;&nbsp;&nbsp;SPI_MasterTransmit(&#039;A&#039;);

&nbsp;&nbsp;&nbsp;&nbsp;//YOUR CODE

&nbsp;&nbsp;&nbsp;&nbsp;//USB TEST
&nbsp;&nbsp;&nbsp;&nbsp;usb_reply[0] = 1;
&nbsp;&nbsp;&nbsp;&nbsp;usb_reply[1] = 2;
&nbsp;&nbsp;&nbsp;&nbsp;usb_reply[2] = 3;
&nbsp;&nbsp;&nbsp;&nbsp;usb_reply[3] = 4;
&nbsp;&nbsp;&nbsp;&nbsp;usb_reply[4] = 5;
&nbsp;&nbsp;&nbsp;&nbsp;usb_reply[5] = 6;
&nbsp;&nbsp;&nbsp;&nbsp;usb_reply[6] = 7;
&nbsp;&nbsp;&nbsp;&nbsp;usb_reply[7] = 8;
&nbsp;&nbsp;&nbsp;&nbsp;usb_reply[8] = 0;
&nbsp;&nbsp;&nbsp;&nbsp;usb_reply[9] = 0;
&nbsp;&nbsp;}
&nbsp;&nbsp;return 0;
}
</pre></pre>
</p></div>
<p>
<strong>MORE INFORMATION</strong></p>
<p>You can find more information about the API / USB Device Class / Host Software on the <a href="http://vusb.wikidot.com/" target="_blank">wiki of V-USB</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.workinprogress.ca/v-usb-tutorial-software-only-usb-for-mega-tiny/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>speech recognition &amp; arduino</title>
		<link>http://www.workinprogress.ca/speech-recognition-arduino/</link>
		<comments>http://www.workinprogress.ca/speech-recognition-arduino/#comments</comments>
		<pubDate>Wed, 26 Aug 2009 22:36:28 +0000</pubDate>
		<dc:creator>psc</dc:creator>
				<category><![CDATA[Electronics]]></category>

		<guid isPermaLink="false">http://www.workinprogress.ca/?p=428</guid>
		<description><![CDATA[Speech recognition done with Simon]]></description>
			<content:encoded><![CDATA[<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="400" height="300" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://vimeo.com/moogaloop.swf?clip_id=6276108&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=00ADEF&amp;fullscreen=1" /><embed type="application/x-shockwave-flash" width="400" height="300" src="http://vimeo.com/moogaloop.swf?clip_id=6276108&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=00ADEF&amp;fullscreen=1" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p>Speech recognition done with Simon</p>
]]></content:encoded>
			<wfw:commentRss>http://www.workinprogress.ca/speech-recognition-arduino/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

