tag:blogger.com,1999:blog-24108895823523670612024-02-18T22:33:47.249-08:00CamelpunchStevehttp://www.blogger.com/profile/14070951525184172272noreply@blogger.comBlogger14125tag:blogger.com,1999:blog-2410889582352367061.post-27343923034572964042012-05-28T09:36:00.001-07:002012-05-28T09:37:15.343-07:00Our Name in Lights<div style="margin: 0px auto 10px; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7KNJfNEsRsrMrkjdpE2Eb6w4ffenZ_4IFm9SRTaqDNUuZCQcw_21vz0r40-4qXrMODtKhgbAx0OUTao6GchZHOcdBPEU31X6dB7mOc7lpL8saUU4nKncksfoAUTBlknI5Fou3d8krxr_9/s1600/2012-05-17+18.06.14.jpg"><img alt="" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7KNJfNEsRsrMrkjdpE2Eb6w4ffenZ_4IFm9SRTaqDNUuZCQcw_21vz0r40-4qXrMODtKhgbAx0OUTao6GchZHOcdBPEU31X6dB7mOc7lpL8saUU4nKncksfoAUTBlknI5Fou3d8krxr_9/s320/2012-05-17+18.06.14.jpg" /></a> </div>
<div style="clear: both; text-align: CENTER;">
<a href="http://picasa.google.com/blogger/" target="ext"><img align="middle" alt="Posted by Picasa" border="0" src="http://photos1.blogger.com/pbp.gif" style="-moz-background-clip: initial; -moz-background-inline-policy: initial; -moz-background-origin: initial; background: transparent none repeat scroll 0% 50%; border: 0px none; padding: 0px;" /></a></div>Stevehttp://www.blogger.com/profile/14070951525184172272noreply@blogger.com0tag:blogger.com,1999:blog-2410889582352367061.post-10356791042562270172010-06-20T16:17:00.000-07:002010-06-20T16:58:27.904-07:003D Video on the CheapSo the other day I was thinking about how 3D images are put together because we got a new 3D TV at work. It occurred to me that I had all the crap at home to build a small 3D video rig myself since over the last several years both of my daughters asked for and got some cheap Flip Video cameras. They're the original Flip Video camera, the 640x480 25fps ones.<br />
<br />
I went to Pini's Hardware and picked up a few items to build a small stereo camera rig. It's comprised of a piece of cheap wood (a wooden garden stake), some half inch wooden dowel, some quarter inch furniture glides and some T-nut fasteners.<br />
<br />
I assembled them like this:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXr_l3AXkaXbCBpNHXLWitl95AyGMUi6_8wqeNsUub1diBj4Z1Fvqpm_Z_mClkq5N9xxY8zo3s-QppEJNtZi1EAMPwceuIp77PsTuV2TxxXFu6WWBLePV8QfSqdZNQWbmKFVmDiP0Mns5t/s1600/IMG_7592.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="427" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXr_l3AXkaXbCBpNHXLWitl95AyGMUi6_8wqeNsUub1diBj4Z1Fvqpm_Z_mClkq5N9xxY8zo3s-QppEJNtZi1EAMPwceuIp77PsTuV2TxxXFu6WWBLePV8QfSqdZNQWbmKFVmDiP0Mns5t/s640/IMG_7592.JPG" width="640" /></a></div><br />
<br />
<br />
<br />
It turns out the that "camera shoe" bolt is really just a standard 1/4" bolt and you can go to the hardware store and get a bolt that'll mount a camera anywhere. It's not some special format like I thought maybe it was.<br />
<br />
Here's what I bought at Pini's. I got enough stuff to make two of these (or screw up one and make one good one, which is generally how I roll.)<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnC9tala0p3tU2Sbwr7kE-r6HdpUiRz2ouYfWlg_nuOGuQnuEEZolXS1hckGXt56AUhTwrmNAhmzi9KpkhpPc02Lf5BYAnCXpWTR35EAlmAuQwfiSJ34YLEfsHCLZ-FTyaSS9KEny5jiFJ/s1600/annotated.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="590" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnC9tala0p3tU2Sbwr7kE-r6HdpUiRz2ouYfWlg_nuOGuQnuEEZolXS1hckGXt56AUhTwrmNAhmzi9KpkhpPc02Lf5BYAnCXpWTR35EAlmAuQwfiSJ34YLEfsHCLZ-FTyaSS9KEny5jiFJ/s640/annotated.png" width="640" /></a></div><br />
Hit "Read More" to hear all about it and see some sample movies.<br />
<br />
<br />
<a name='more'></a><br />
<br />
The build process was:<br />
<br />
1. Measure everything and mark with pencil<br />
2. Drill pilot holes for camera mounts<br />
3. Drill slightly larger pilot holes on the bottom for the T-nut fasteners<br />
4. Bang fasteners into place<br />
5. Screw furniture glides into bottom of T-nuts.<br />
6. Drill 1/2" dowel holes halfway through on top<br />
7. Mount dowels<br />
8. Drill screw pilot holes from bottom up through dowels<br />
9. Glue and screw dowels into place.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpuDZZPKhyYbhSzlFf471FQ5DoBFHbJENP-NF8AaFGZl5wrJ76N5Nkv0PS7q0qtMHFOF6ESRJ5t4MVp8hwpF_Rh_WI_s-XOkrEOcNhqHQP1UiR-M1ulgtLmTkoUjZLH00M5DhLWtvcZD2W/s1600/IMG_7587.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="428" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpuDZZPKhyYbhSzlFf471FQ5DoBFHbJENP-NF8AaFGZl5wrJ76N5Nkv0PS7q0qtMHFOF6ESRJ5t4MVp8hwpF_Rh_WI_s-XOkrEOcNhqHQP1UiR-M1ulgtLmTkoUjZLH00M5DhLWtvcZD2W/s640/IMG_7587.JPG" width="640" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEZjJZjcur2toGSWfU2Zz1V07K5b_J_sgLkdpk8RcOstSkYjwRBxfNEKxzDdeWX7KpZ3ZKF0e-EFU4gvNKCHgvFLV3CchcaaYNaDL-DEkvdm3TcU6obqx50AP3E_E83aRr03Z8mlqhFQFf/s1600/IMG_7588.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="428" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEZjJZjcur2toGSWfU2Zz1V07K5b_J_sgLkdpk8RcOstSkYjwRBxfNEKxzDdeWX7KpZ3ZKF0e-EFU4gvNKCHgvFLV3CchcaaYNaDL-DEkvdm3TcU6obqx50AP3E_E83aRr03Z8mlqhFQFf/s640/IMG_7588.JPG" width="640" /></a></div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhz0imkfmKvHBSVdf_eaEiaBN9Kpugs43TffsJ434wX7iVtQb1fRg9RLQxtNc0BHukccus_XnUde2gLpqd-gI52y4OUfmZeCj6LuDxD6_b1IcEa-L6LTRaaAusQJUw9c7L9-40Qu58A0kYG/s1600/IMG_7590.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="428" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhz0imkfmKvHBSVdf_eaEiaBN9Kpugs43TffsJ434wX7iVtQb1fRg9RLQxtNc0BHukccus_XnUde2gLpqd-gI52y4OUfmZeCj6LuDxD6_b1IcEa-L6LTRaaAusQJUw9c7L9-40Qu58A0kYG/s640/IMG_7590.JPG" width="640" /></a></div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: left;">I mounted the dowels as I did to allow me to hold onto the whole rig while simultaneously pressing the "record video" buttons with both thumbs. In practice it works pretty well but even so, there's a small variance in start up times.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">As you can see here, it's easy to reach the record buttons on the Flip Video cameras while holding the dowels. Holding the camera rig with two hands helps keep it stable too.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVjIBJpbu-JVieX98akbsA4rvJ4DsqkbCfPEPFDjiaHKveCKBdkV2cmkLepnh-lVGUr3iI_XDSMn91FyTDgxw2t6rObCVRq6WCFjsFEZwJM3LLGae0VK6SiSJxYJv5IkeeDTElOCRiRyk7/s1600/IMG_7594.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="428" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVjIBJpbu-JVieX98akbsA4rvJ4DsqkbCfPEPFDjiaHKveCKBdkV2cmkLepnh-lVGUr3iI_XDSMn91FyTDgxw2t6rObCVRq6WCFjsFEZwJM3LLGae0VK6SiSJxYJv5IkeeDTElOCRiRyk7/s640/IMG_7594.JPG" width="640" /></a><br />
<div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">The important part to get right is the lens spacing, which needs to be approximately 6.35 centimeters. If you use the same model camera as I did, then just making sure to space the mounting holes at 6.35 centimeters does the trick:</div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzU4zThyphenhyphenbz4j0hElrG5_FPMkLBOlpRAkywyd0RIq3iDylQdfSdhAR2iQRc5EKiWCz0mq-l9wF-xjEOZ3DeB00MHSKMcTWYc1rQ2ldfe_dpo3VihBkl3E7SmIbQi2vQNwpBIfVNmwTWir0Z/s1600/IMG_7593.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="428" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzU4zThyphenhyphenbz4j0hElrG5_FPMkLBOlpRAkywyd0RIq3iDylQdfSdhAR2iQRc5EKiWCz0mq-l9wF-xjEOZ3DeB00MHSKMcTWYc1rQ2ldfe_dpo3VihBkl3E7SmIbQi2vQNwpBIfVNmwTWir0Z/s640/IMG_7593.JPG" width="640" /></a></div><br />
And this project was cheap! Not counting the cost of the cameras, It was under $5 to put this whole thing together.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqXG2mv2ZYVfjX-CMMZNI4M1drRu3F0XkDnPWqX8Y6dbz0NvBWGnBh8zGubh4z2yz-KFg6gHeLnxeHKV1cj4rl2eOm28ETAtGeIJ-XtPb1WG9YTYjG3lzFzf55dzG-6I6i7IgnLg7alzBr/s1600/receipt.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqXG2mv2ZYVfjX-CMMZNI4M1drRu3F0XkDnPWqX8Y6dbz0NvBWGnBh8zGubh4z2yz-KFg6gHeLnxeHKV1cj4rl2eOm28ETAtGeIJ-XtPb1WG9YTYjG3lzFzf55dzG-6I6i7IgnLg7alzBr/s640/receipt.jpg" width="491" /></a></div><br />
Ignore the charcoal and lawn irrigation parts.<br />
<br />
So that's the build. Again, here's the end result with everything mounted:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1s3m1PZIExCbXSpPk9DSK2G3WRTb0kJ6c6sA5IxW8EpALaEaP3EpbCfUUAtogTeuOJZ_Ly1whDInD4eRCWwp_QJIIULLPuCtLdKQvKipTU01wC3_fQxcbnBjh-IK2_gs4rkMul5g-GQVS/s1600/IMG_7591.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="428" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1s3m1PZIExCbXSpPk9DSK2G3WRTb0kJ6c6sA5IxW8EpALaEaP3EpbCfUUAtogTeuOJZ_Ly1whDInD4eRCWwp_QJIIULLPuCtLdKQvKipTU01wC3_fQxcbnBjh-IK2_gs4rkMul5g-GQVS/s640/IMG_7591.JPG" width="640" /></a></div><br />
So how does it work? Surprisingly well, actually!<br />
<br />
I shot some test videos yesterday and then took it out on a walk today. The biggest issues are:<br />
<br />
1. Lining up the shots in the frame.<br />
2. Synchronizing the movies to start together.<br />
<br />
Fortunately the software I'm using, <a href="http://stereo.jpn.org/eng/stvmkr/">Stereo Movie Maker</a>, allows you to adjust horizontal, vertical, and timeline alignment to synchronize and align everything.<br />
<br />
I've produced side-by-side 3D videos and red/cyan anaglyph videos.<br />
<br />
The side-by-sides can be viewed in 3D by putting a stiff piece of cardboard between your eyes and the monitor running vertically between the two images to split the image down the middle. If you relax your eyes until you see one image, it will appear in 3d. You cannot cross your eyes to see these images in 3d, the images are in the wrong order for that. I find that crossing eyes to view 3d images causes me instant headache and the images look blurry so I didn't even try to compose the movies that way.<br />
<br />
The Red/Cyan Anaglyph images require red/cyan glasses like you'd get with some DVD promotions. There are several different color separation techniques for viewing 3D images. Red/Cyan, Red/Blue, Red/Green, Yellow/Purple. I chose Red/Cyan because it's the most common.<br />
<br />
Click on an image to download the full movie to your computer.<br />
<div style="text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><img border="0" height="192" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnaI4ZAjPctgcM7YiBjcnK86Eo8leeQi6pLMpKgXdJ9bSp5j1tExmDhhL3Fqx5o2fpNhz8BC8o_7P_UPNgC8sA5Ke0pIuH9U0qWwNgowxRI3gUs2mNRYcmNqoEi9gey63YSGiRylyzUy6k/s400/sprocket4.PNG" width="400" /></div><div class="separator" style="clear: both; text-align: center;"><a href="http://www.box.net/shared/1s2kx4sn63">Sprocket side-by-side</a></div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div style="text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpfqhfIfAWff_e_OoxGynlOk6klSmIGQfF3OiVK5meKqlMxo4WCiYI0MJIXIwKxYtO_fG2MGJCFtda8WrDC-hVGMsewbMEI5wtMbpcMamyCdBR6On22g3XagAstb0Sm7A4GDXYjUUYnMhI/s320/sprocket4-red-cyan-anaglyph.PNG" /></div><div class="separator" style="clear: both; text-align: center;"><a href="http://www.box.net/shared/bbnpeikxux">Sprocket Red/Cyan Anaglyph</a></div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div style="text-align: center;"><img border="0" height="140" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKbsMu40wlsq1A68TPeFL6swWJkorYdJz8K4JtdF70uhxb7I60cnJZkAec8XoX-u8vkE3CjjfXIsBZgjni5srLOeeYuLZ8jgyCuuI7C8ZCUpoF5KJfK1WQrRjNL3vganHLGOqKKvFmGC3t/s400/buttons1.PNG" width="400" /></div><div class="separator" style="clear: both; text-align: center;"><a href="http://www.box.net/shared/avgc7ho29r">Buttons side-by-side</a></div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><img border="0" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgi-T5yaP-R5l1p8age5aLJfq1rkAXSly7wHFumCk_ytHZ4fq6D_cfrWDy1Md3eTtuPxV37PRa2zA1_akvlQjQ2sl9VhgzE_RldXkzEl52qde7NqfaJdrjZRCp0WGQw43DgmbP33BQkjeLH/s400/haleyleaf.PNG" width="400" /></div><div class="separator" style="clear: both; text-align: center;"><a href="http://www.box.net/shared/rtmeaq7ujj">Haley with Leaf side-by-side</a></div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><img border="0" height="141" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvwX08BJxuWMCd-e4d_M_L5iRr0PHsG7aW3Ovhg-CJi324EpRE0pFGc4pxPmevoK7QPxU0_o2oBjisySQfkF0l_h90L6SnsgUQI6fdcZH0Tp99kWqOFUT18qlOiJcWmAInF7uLwwWbFNJK/s400/horseshoes.PNG" width="400" /></div><div class="separator" style="clear: both; text-align: center;"><a href="http://www.box.net/shared/u7g413o4xl">Horseshoes side-by-side</a></div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div style="text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikiFguQ6UBda1dvo7W2iqcZpyxd7g08_nJcL6Bv8pzTa6CswSj-A0JmxhlOMaZ71MW4bbG225__eY_ZZZIphR5OzxDowzrA_0igKI0LUSvc56YhdtQSKCeyDOQXUNVS-8KbDrpSVCGx87Z/s320/horseshoes-red-cyan-anaglyph.PNG" /></div><div class="separator" style="clear: both; text-align: center;"><a href="http://www.box.net/shared/qrivo38llu">Horseshoes Red/Cyan Anaglyph</a></div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><img border="0" height="147" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUwOvFaQ0dZ70wvUuZ8Ddn6PBTxPxIkIEUnppY1yvTih9PyxUUGun1qGZxnw6O6LcaLS4h8ZYj43IfVby6B49GpwpOQFPzlKH7lOB_Kn45PzHUu1_Vp3_dU18II_lKQpPLWFg1lrMI3lxm/s400/zoestream.PNG" width="400" /></div><div class="separator" style="clear: both; text-align: center;"><a href="http://www.box.net/shared/57jtcxfobs">Zoe and Lucky in the Stream side-by-side</a></div><div class="separator" style="clear: both; text-align: center;"><br />
</div>You can view them on your monitor, but may need to resize the movie so that your eye-to-screen distance is large enough to allow proper convergence of the two image (if you're using the cardboard card method of viewing described above.)<br />
<br />
Let me know how they work for you. And those of you with red/cyan glasses, please try those out. I don't have any anaglyph glasses yet and am currently trying to track some down.Stevehttp://www.blogger.com/profile/14070951525184172272noreply@blogger.com1tag:blogger.com,1999:blog-2410889582352367061.post-55013828807402615132010-02-21T14:56:00.000-08:002010-02-21T17:44:08.485-08:00The Brushduino<div>Ever have an idea that people tell you "you should TOTALLY patent that!" Well, I did, and they did, and I thought about it... but instead I decided to open source the whole thing. It seemed like kind of an obvious idea to me and going after a patent made me feel kind of greedy. Besides, all of my prototyping was done with open source tools! </div><div><br />
</div><div>Anyways, I hope someone can improve upon this. I think it's a useful thing.</div><br />
<b>The Story</b> <br />
<br />
My daughters don't brush their teeth long enough, if left to their own devices. When my wife or I brush their teeth, we do a nice thorough job that takes a little while but when the girls do it themselves, they tend to cut it short. Timing them doesn't help, as they just stand there and chit-chat until the timer goes off. It's not that they don't brush their teeth LONG enough, it's that they don't brush their teeth WELL enough. <br />
<br />
It occurred to me that if could make something that monitored how WELL they brush their teeth---and maybe even guided them through the process a little---then they'd eventually establish better habits for the future. I started thinking about what I could build that would help them and settled on the notion that an accelerometer was the perfect sort of thing to keep tabs on what constitutes a brush "stroke" while they're in there brushing their teeth. All I'd need to do is come up with a little hardware and software to make it happen. <br />
<br />
<div><b>About the Hardware</b></div><br />
For my birthday last year, I got myself an <a href="http://www.arduino.cc/">Arduino </a>starter kit from <a href="http://www.adafruit.com/">www.adafruit.com</a> and hadn't used it for anything yet. I was curious about the Arduino platform and have read a lot about it. I figured it was time to build something on it and this toothbrush thing seemed like the perfect fit. <br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5y0OBbMJCyk_D23M7Xgsi6sLzlD_12jL4dGmQRu8sEuXqnx6dkgq__eD4GVqdI-qQh9gJfeRJMzxW-KKMD-YDbniHv79-8gZgcP8D3mfxED9UmfyvRsJWbu0_KkqcxgkBP2kU8vHkMulN/s1600-h/IMG_6399.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5440841898986472002" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5y0OBbMJCyk_D23M7Xgsi6sLzlD_12jL4dGmQRu8sEuXqnx6dkgq__eD4GVqdI-qQh9gJfeRJMzxW-KKMD-YDbniHv79-8gZgcP8D3mfxED9UmfyvRsJWbu0_KkqcxgkBP2kU8vHkMulN/s400/IMG_6399.jpg" style="cursor: hand; cursor: pointer; display: block; height: 267px; margin: 0px auto 10px; text-align: center; width: 400px;" /></a> <br />
<br />
I started looking for a low-cost accelerometer I could base my project on. I found one with a breakout board on Adafruit and one on Sparkfun but I didn't want to spend that much. Plus, it needed to be small---I wanted this thing to fit on the end of a toothbrush. I continued scouring the web and found this article over on <a href="http://hackaday.com/">Hack a Day</a> for <a href="http://hackaday.com/2009/05/20/digital-dice/">Digital Dice</a>. This was based around the <a href="http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=MMA7260QT">Freescale MMA7260QT</a> and he fearlessly did all of the fine soldering work himself. I figured I could do that too. I ordered up a couple of MMA7260QT's from <a href="http://www.mouser.com/search/ProductDetail.aspx?qs=H7uYjNJSR1XDeUvfUNRFgg%3D%3D">Mouser</a> and a couple of the MMA7368LT's (BGA package version) and set to work with 30 AWG tynar coated solid core wire. This stuff is usually used for wire-wrapping, but I like to use it for low-current point to point stuff and general purpose project wire. <br />
<br />
I wired one of the MMA7368LT's up to a .1" pin header so I could start experimenting. <br />
<div><br />
</div><div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMsanr17schc7hyuuep7d0_5tTRRzXuq_fnIF-Ym1b2YjPylzUtiePzb8ApGsgjuqvPoVLga-F0hZiVDwE4ZIz_P3x-oUYnV-K6XuCLaZLx5F0r5O-Z5GFbu2blxf7Ov_6X3alNn8Yo_rp/s1600-h/BGA-closeup.gif" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5440843069786931154" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMsanr17schc7hyuuep7d0_5tTRRzXuq_fnIF-Ym1b2YjPylzUtiePzb8ApGsgjuqvPoVLga-F0hZiVDwE4ZIz_P3x-oUYnV-K6XuCLaZLx5F0r5O-Z5GFbu2blxf7Ov_6X3alNn8Yo_rp/s400/BGA-closeup.gif" style="cursor: pointer; display: block; height: 373px; margin-bottom: 10px; margin-left: auto; margin-right: auto; margin-top: 0px; text-align: center; width: 400px;" /></a></div><div style="text-align: center;"><span class="Apple-style-span" style="color: #0000ee;"><u> <br />
</u></span></div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMsanr17schc7hyuuep7d0_5tTRRzXuq_fnIF-Ym1b2YjPylzUtiePzb8ApGsgjuqvPoVLga-F0hZiVDwE4ZIz_P3x-oUYnV-K6XuCLaZLx5F0r5O-Z5GFbu2blxf7Ov_6X3alNn8Yo_rp/s1600-h/BGA-closeup.gif" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"></a><br />
<div>It's pretty fiddly work and requires lots of swearing. I drink a lot of caffeine, which makes it even harder. I recommend finding great inner peace before you begin. Some solder paste also helps. </div><div><br />
</div><div><br />
</div><div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSB5sa5Wm86zSkwk8cOXnR61P5NW6PsHoFpx8UdkCjcPIuh5aSe9G0V0wcWz_A_-IzWchzBWiq0ANAmxhgLb7k5gHPn2pUnTlToilstIqUKf6L-H7cu7lF6mXfKwGGNbfZwCDipYM3FAJk/s1600-h/Kester.gif" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5440845134176378594" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSB5sa5Wm86zSkwk8cOXnR61P5NW6PsHoFpx8UdkCjcPIuh5aSe9G0V0wcWz_A_-IzWchzBWiq0ANAmxhgLb7k5gHPn2pUnTlToilstIqUKf6L-H7cu7lF6mXfKwGGNbfZwCDipYM3FAJk/s400/Kester.gif" style="cursor: pointer; display: block; height: 179px; margin-bottom: 10px; margin-left: auto; margin-right: auto; margin-top: 0px; text-align: center; width: 400px;" /></a></div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSB5sa5Wm86zSkwk8cOXnR61P5NW6PsHoFpx8UdkCjcPIuh5aSe9G0V0wcWz_A_-IzWchzBWiq0ANAmxhgLb7k5gHPn2pUnTlToilstIqUKf6L-H7cu7lF6mXfKwGGNbfZwCDipYM3FAJk/s1600-h/Kester.gif" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"></a><br />
<div><br />
</div><div>I got everything going with the Arduino just jumpering things around and with a bit of breadboard. It all went very quickly compared thanks to the Arduino environment which took care of a lot of the usual setup I normally go through (soldering up a voltage regulator, breaking out the SPI pins for programming AVR chips, setting fuses, burn-and-test-and-burn-and-test, etc.) It was nice! </div><div><br />
</div><div>If the Arduino is the brain of this project and the accelerometer is the eyes, then the <a href="http://www.ladyada.net/make/pshield/">Adafruit ProtoShield</a> is the heart. It's only like <a href="http://www.adafruit.com/index.php?main_page=product_info&cPath=17_21&products_id=51">$13</a> and it's brilliant.</div><div><br />
</div><div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinjyB974nLYTdPFYv5uRLH7orzf5YEm_lmDgsEKT3B_868p2zSOmB22NWXdG-kMko1D0A3TaWbJWtoIGGshc0jtw9lj920P3oEupnfXjO_CY4U84T3K2KQ_gtdS9k5sg3BioRYMbAbBQ_7/s1600-h/Protoshield.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5440846872257977250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinjyB974nLYTdPFYv5uRLH7orzf5YEm_lmDgsEKT3B_868p2zSOmB22NWXdG-kMko1D0A3TaWbJWtoIGGshc0jtw9lj920P3oEupnfXjO_CY4U84T3K2KQ_gtdS9k5sg3BioRYMbAbBQ_7/s400/Protoshield.jpg" style="cursor: pointer; display: block; height: 245px; margin-bottom: 10px; margin-left: auto; margin-right: auto; margin-top: 0px; text-align: center; width: 400px;" /></a></div><div><br />
</div><div>It's basically all LED's. There are 6 white LED's that correspond to the six regions of the mouth that I want to highlight, there are four green LED's for showing progress and there's a speaker I pulled out of some broken toy that's there to entertain the children while they brush. The multi-strand wire connected to the three analog inputs on the Arduino also supplies 3.3v and ground to the accelerometer. The cable itself is an old ADB keyboard cable from my old Mac SE/30 from back in the day. It's been laying in my junk box for ages. There are also some current limiting resistors for the LED's and a bunch more of that lovely AWG30 solid core wire I like so much.</div><div><br />
</div><div>At the toothbrush end of the cable, I encased the whole thing in hot glue to keep it safe from water and from yanking by children:</div><div><br />
</div><div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8WCxsNEqqfamiKXDDWRW4_0_niZZlp-RqWGduF0NFV0a01SPTCAnx7A8IABRODaJELbw6Gdd-L_oxHgA77buZJXSK8LtGQm31wY7xs8eOOyW9AaSX70h1Ty6jnsmz1FT2EyxO1-YqnXHh/s1600-h/IMG_6404.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5440848564585093890" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8WCxsNEqqfamiKXDDWRW4_0_niZZlp-RqWGduF0NFV0a01SPTCAnx7A8IABRODaJELbw6Gdd-L_oxHgA77buZJXSK8LtGQm31wY7xs8eOOyW9AaSX70h1Ty6jnsmz1FT2EyxO1-YqnXHh/s400/IMG_6404.jpg" style="cursor: pointer; display: block; height: 267px; margin-bottom: 10px; margin-left: auto; margin-right: auto; margin-top: 0px; text-align: center; width: 400px;" /></a></div><div>This "puck" on the end was meant to be attached to the toothbrush handle via some mechanism (I ended up using rubber bands, which was only somewhat successful and I hope to improve upon) and held in the user's hands.</div><div><br />
</div><div>For an enclosure, I used a <a href="http://www.pactecenclosures.com/Plastic-Enclosures/PPLX-9VB_2AA.html">cool plastic enclosure</a> I got from <a href="http://www.pactecenclosures.com/">PAC TEC</a> a few years ago as a free sample. It was perfect for housing the Arduino with attached <a href="http://www.ladyada.net/make/pshield/">ProtoShield </a>and had a 9 Volt Battery compartment too. I had to modify the battery compartment and I added a barrel connector so I didn't have to solder to the Arduino at all.</div><div><br />
</div><div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnTGc17Xf7lLi52jGWF5gF8OsgJhFgBrpoIZ1SLxRBLgAZiLOs-ug-x-cyI6kI6Nj_-nFjPhzztTLQailPgAzI36EIio947iH3RP1lkUtQA3yRn_fEaNFD_tR_ryl2F5Hmw_KMyssjE8hZ/s1600-h/IMG_6405.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5440848573425727666" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnTGc17Xf7lLi52jGWF5gF8OsgJhFgBrpoIZ1SLxRBLgAZiLOs-ug-x-cyI6kI6Nj_-nFjPhzztTLQailPgAzI36EIio947iH3RP1lkUtQA3yRn_fEaNFD_tR_ryl2F5Hmw_KMyssjE8hZ/s400/IMG_6405.jpg" style="cursor: pointer; display: block; height: 267px; margin-bottom: 10px; margin-left: auto; margin-right: auto; margin-top: 0px; text-align: center; width: 400px;" /></a></div><div>To allow the indicator lights to show through the case to the front and still remain waterproof, I used some more hot glue. I drilled holes roughly the size of the LED's directly above where they would fall once installed in the case, filled the holes with hot glue, and snipped off the tops and bottoms to be flush against the case on the top side and flush against the LED's on the bottom side. For the reset button, I used the same technique, but lubricated the hole so the hot glue piece can slide up and down. It all proved to be pretty water tight and while the hot glue is a little opaque, it's clear enough to transfer the light up to the surface where they can see it. It's a sort of a "light pipe" type of thing.</div><div><br />
</div><div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhb9lHqeszXodUwEUHisHGfTzdyXBAHUv3sPQAmNrah7ianx-IELZQV34Y1oKlpOKcLn7et1d-_wcgO1EPb5mX9muEG3fY4haDJPkLpwmQmEVcRc9aB59f1STBDNwcXw8Nv8au04ba7tl1l/s1600-h/IMG_6406.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5440848580849669538" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhb9lHqeszXodUwEUHisHGfTzdyXBAHUv3sPQAmNrah7ianx-IELZQV34Y1oKlpOKcLn7et1d-_wcgO1EPb5mX9muEG3fY4haDJPkLpwmQmEVcRc9aB59f1STBDNwcXw8Nv8au04ba7tl1l/s400/IMG_6406.jpg" style="cursor: pointer; display: block; height: 267px; margin-bottom: 10px; margin-left: auto; margin-right: auto; margin-top: 0px; text-align: center; width: 400px;" /></a></div><div>Above you can see the barrel connector for the arduino peeking out and the SPST slide switch I installed in the side of the case.</div><div><br />
</div><div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYOrf14Q06b-V8PhPshmO0yIWcR_Qql1Nc6ZpJeI-BRDVxGLeTcLYudVy7r6nApc-eaD81rKQXAvPg7SLIwmEcPciq7w0G3H6CkOEuwxtDWzFff0v1VlbqKCSPciTq4aOH_sTTMFxHc9wv/s1600-h/IMG_6407.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5440848595932128290" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYOrf14Q06b-V8PhPshmO0yIWcR_Qql1Nc6ZpJeI-BRDVxGLeTcLYudVy7r6nApc-eaD81rKQXAvPg7SLIwmEcPciq7w0G3H6CkOEuwxtDWzFff0v1VlbqKCSPciTq4aOH_sTTMFxHc9wv/s400/IMG_6407.jpg" style="cursor: pointer; display: block; height: 267px; margin-bottom: 10px; margin-left: auto; margin-right: auto; margin-top: 0px; text-align: center; width: 400px;" /></a>I repurposed some orange suction cups from a cheap nerf hoop knockoff toy I got as a Christmas present one year to stick the enclosure to the girls' mirror in the bathroom to keep it at eye level and keep it out of the water.</div><div><br />
</div><div>Here it is installed over their sink:</div><div><br />
</div><div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDJHjZ_unh4DPYk-ZLjKLnhd5moXk3s4pijlvfVLDhqBn93l5lP5S2Jt-0h3L_vUyy03gc6arzGNJMIkQxK2uC2UYKM1BJJLH53CZnqMjiadg7rs-ZEQ7f4UP87QukkLPB-8uF3rNeMwjd/s1600-h/IMG_6423.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5440850347673662402" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDJHjZ_unh4DPYk-ZLjKLnhd5moXk3s4pijlvfVLDhqBn93l5lP5S2Jt-0h3L_vUyy03gc6arzGNJMIkQxK2uC2UYKM1BJJLH53CZnqMjiadg7rs-ZEQ7f4UP87QukkLPB-8uF3rNeMwjd/s400/IMG_6423.jpg" style="cursor: pointer; display: block; height: 267px; margin-bottom: 10px; margin-left: auto; margin-right: auto; margin-top: 0px; text-align: center; width: 400px;" /></a></div><div><br />
</div><div>When you fire it up, it plays the opening bars of the Super Mario Brothers theme song while randomly flashing the white LED's. Then it starts instructing on what area of the mouth to brush.</div><div><br />
</div><div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinlhjbHzgGL-1nXmiuWYMAQpw8ZCOVsgacgT1-rFBp1eydSheQKv3XTRbPfts8EuZwG2ELcjQFFOI1QRz5WjuGz_WnMxxDiiGgRKmuP-YOpkqZbt0ZFhgghjVEzi-kZZ-sTTKHsbz1k_Oh/s1600-h/IMG_6416.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5440852049174836274" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinlhjbHzgGL-1nXmiuWYMAQpw8ZCOVsgacgT1-rFBp1eydSheQKv3XTRbPfts8EuZwG2ELcjQFFOI1QRz5WjuGz_WnMxxDiiGgRKmuP-YOpkqZbt0ZFhgghjVEzi-kZZ-sTTKHsbz1k_Oh/s400/IMG_6416.jpg" style="cursor: pointer; display: block; height: 267px; margin-bottom: 10px; margin-left: auto; margin-right: auto; margin-top: 0px; text-align: center; width: 400px;" /></a></div><div><br />
</div><div>I draw a mouth on a piece of paper and glue-stick it to the front. That way I can rotate the pictures out and keep them funny/interesting. The green LED that's lit rotates around between the four as each "stroke" is counted. A "stroke" is defined as hard acceleration in one direction followed by hard acceleration in the opposite direction within a specified time window. I tweaked the parameters of what defines a "stroke" until I got pretty good results. It still picks up false strokes when they're moving the toothbrush around but it does a pretty good job. At least---good enough for this purpose.</div><div><br />
</div><div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDG58bujsNb3BXgLQ7gWb53W5FGVNqJJNmoBHgtL0pVV-INRjnu2L_dicaSt9gHj1yVSEdZEJlPKzB8Rn3sax9OEI_YAyo3ikGWBhiu2dw68kVa1fm00lkmrctISG7NNwp7Siy8mk-zGC0/s1600-h/IMG_6418.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5440852055134909394" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDG58bujsNb3BXgLQ7gWb53W5FGVNqJJNmoBHgtL0pVV-INRjnu2L_dicaSt9gHj1yVSEdZEJlPKzB8Rn3sax9OEI_YAyo3ikGWBhiu2dw68kVa1fm00lkmrctISG7NNwp7Siy8mk-zGC0/s400/IMG_6418.jpg" style="cursor: pointer; display: block; height: 267px; margin-bottom: 10px; margin-left: auto; margin-right: auto; margin-top: 0px; text-align: center; width: 400px;" /></a></div><div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgwiqzGh0aYGqrvL_1gtbsMIBxcmkHJYQzbuFTv9hOYcmPPFOZZPPfVhrKDccYB8O0JMXd4I4gBohQIQXU20w5RCPXdzEYdfo3bMZtRn3Cb6aABYBXONNPNXGaqO_N1C3lM54pLLHemqPt/s1600-h/IMG_6421.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5440852062355416034" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgwiqzGh0aYGqrvL_1gtbsMIBxcmkHJYQzbuFTv9hOYcmPPFOZZPPfVhrKDccYB8O0JMXd4I4gBohQIQXU20w5RCPXdzEYdfo3bMZtRn3Cb6aABYBXONNPNXGaqO_N1C3lM54pLLHemqPt/s400/IMG_6421.jpg" style="cursor: pointer; display: block; height: 267px; margin-bottom: 10px; margin-left: auto; margin-right: auto; margin-top: 0px; text-align: center; width: 400px;" /></a></div><div><br />
</div><div>Each time a section of the mouth has been brushed sufficiently (stroke count was based on experimentation and dentist recommendations) a few more bars of the Super Mario Brothers theme song is played (along with light show) and then the next white LED starts flashing. It's easier to see the pattern than it is to describe it. The section they're supposed to be brushing at any point in time is blinking with the already-brushed portions of the mouth lit fully on.</div><div><br />
</div><div>Here's a video of the whole process with me fake-brushing my way through it. Pardon the nausea-cam photography, I couldn't find my little tabletop tripod.</div><div><br />
<br />
<div style="text-align: center;"><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dxsv3sc-OkKANVz47LXlF9hda_pT2wJ_UIkA98iZVp0fGJ1s2QdA14B4tT4fVjJVkUqOg-eO7985IVkGavNbg' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div><div style="text-align: center;"><br />
</div><div style="text-align: left;">It works pretty well! And my first Arduino project was a smashing success. Let's hear it for easy floating point number support on microcontrollers. </div><div style="text-align: left;"><br />
</div><div style="text-align: left;">My next step is to replace that puck of hot glue on the end with a <a href="http://www.sugru.com/">Sugru </a>"cup" that they stick on the end of the toothbrush. I was lucky enough to get some <a href="http://www.sugru.com/">Sugru </a>for Christmas (actually, after Christmas) and have been itching to use it for something electronic. For those not familiar with <a href="http://www.sugru.com/">Sugru</a>, it's an air-curing silicone putty made by a snazzy little outfit in the UK.</div><div style="text-align: center;"><br />
</div><div style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLsdMIwZg1hexXn6RNTktj0C3n7hVSEOE2y5e4PigWFh2KSgb3Hf65F4X3YURZnEwJtoZ2eShJnB9AS2rzdzyI4hqmS4wJ6wpZMXp4DAK1N2AjVXImyZUZdzZCq4-5SRCZcaV_LoHbDRM7/s1600-h/IMG_6425.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5440852067938638082" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLsdMIwZg1hexXn6RNTktj0C3n7hVSEOE2y5e4PigWFh2KSgb3Hf65F4X3YURZnEwJtoZ2eShJnB9AS2rzdzyI4hqmS4wJ6wpZMXp4DAK1N2AjVXImyZUZdzZCq4-5SRCZcaV_LoHbDRM7/s400/IMG_6425.jpg" style="cursor: pointer; display: block; height: 267px; margin-bottom: 10px; margin-left: auto; margin-right: auto; margin-top: 0px; text-align: center; width: 400px;" /></a></div><div style="text-align: left;"><br />
</div><div style="text-align: left;">I'll post again once I have the <a href="http://www.sugru.com/">Sugru </a>version going. I just ripped out of few of the wires to the accelerometer when cutting the hot glue off so I have to go back to the workshop for a while. :-/</div><div><br />
</div><div>Eventually I'll replace the Arduino with a couple of voltage regulators, a pushbutton and an ATmega328 and make this piece of hardware fully "legit." Or maybe I won't.</div><div><br />
</div><div><b>About the Software</b></div><div><b> <br />
</b></div><div>Coding for Arduino is easy-cheesy compared to working directly with <a href="http://winavr.sourceforge.net/">WinAVR </a>or <a href="http://www.atmel.com/dyn/products/tools_card.asp?tool_id=2725">Atmel's AVR Studio</a>. For one thing, you get printf() which is HUGE! I used LED indicators to debug previously. Being able to log output to a scrollback is an immense boon. It's really pretty luxurious! The Arduino environment is basically a front end for a WinAVR backend and it also gives you some pretty awesome libraries to use straight out of the box.</div><div><br />
</div><div>For the software, I needed to light pretty lights, play pretty music and most importantly count brush strokes.</div><div><br />
</div><div>For those of you who have worked with three axis accelerometers, you know that gravity is always represented in the reading. To get a good sense of movement around three space, you need to subtract out the gravity component from the readings you're getting. This is harder than it sounds if you consider that in my case the toothbrush could be oriented any which way and therefore the gravity could be registering along any axis or any combination of axes. </div><div><br />
</div><div>To solve this problem, I turned to a cheap-o solution which is to use a sort of bargain basement "high pass filter" to remove the gravity component. Since gravity is going to be constant, it stands to reason that whatever elements of motion that the accelerometer is registering, the ones that have been going on for a long time (low frequency data) should be ignored while the recent and rapid changes (high frequency data) should be allowed to go through for analysis. I did a little searching around and found a small Objective C code snippet in the iPhone developers' realm that did just the thing I needed... simulated a high pass filter:</div><br />
<br />
<pre style="border: 1px solid #CCCCCC; color: black; font-family: Fixed, monospace; font-size: 95%;"><span style="color: #7e7e7e;">// Read the 3 axes analog values from the accelerometer</span>
<span style="color: #cc6600;">int</span> rawX = <span style="color: #cc6600;">analogRead</span>(analogXPin) - 512; <span style="color: #7e7e7e;">// read the value from the sensor</span>
<span style="color: #cc6600;">int</span> rawY = <span style="color: #cc6600;">analogRead</span>(analogYPin) - 512; <span style="color: #7e7e7e;">// read the value from the sensor</span>
<span style="color: #cc6600;">int</span> rawZ = <span style="color: #cc6600;">analogRead</span>(analogZPin) - 512; <span style="color: #7e7e7e;">// read the value from the sensor</span>
<span style="color: #7e7e7e;">// Our High Pass filter works better with signed floating point values</span>
<span style="color: #cc6600;">float</span> floatX = (<span style="color: #cc6600;">float</span>)rawX,
floatY = (<span style="color: #cc6600;">float</span>)rawY,
floatZ = (<span style="color: #cc6600;">float</span>)rawZ;
<span style="color: #7e7e7e;">// Low pass filter</span>
<span style="color: #cc6600;">float</span> kFilteringFactor = 0.1f;
<span style="color: #7e7e7e;">// We're keeping 90% of the rolling value and adding in 10% of the new value each</span>
<span style="color: #7e7e7e;">// time. This filters out recent values and retains historical values.</span>
rollingX = (floatX * kFilteringFactor) + (rollingX * (1.0 - kFilteringFactor));
rollingY = (floatY * kFilteringFactor) + (rollingY * (1.0 - kFilteringFactor));
rollingZ = (floatZ * kFilteringFactor) + (rollingZ * (1.0 - kFilteringFactor));
<span style="color: #7e7e7e;">// High pass filter</span>
<span style="color: #7e7e7e;">// Now we remove the historical values to emphasize current values more. The high</span>
<span style="color: #7e7e7e;">// pass filter helps us remove gravity from the reading so we can get orientation-</span>
<span style="color: #7e7e7e;">// independent acceleration values from the device</span>
accelX = floatX - rollingX;
accelY = floatY - rollingY;
accelZ = floatZ - rollingZ;
</pre><br />
<br />
My processed ( accelX, accelY, accelZ ) vector now represents interesting accelerometer values to feed into a little stroke counter routine.</div><div><br />
</div><div>For the music side of the project, I found the <a href="http://www.arduino.cc/playground/">Arduino Playground</a> "freqout()" function, which I modified to handle rests and a wider range of note values. I then found someone's sheet music transcription of the Super Mario Brothers theme song and converted it to data.</div><div><br />
</div><div>Here's the full source code of the Arduino sketch. This was compiled against arduino-0017 but should work with the latest too. Full source after the break below:<br />
<br />
<a name='more'></a><br />
<br />
</div><pre><span style="color: #7E7E7E;">//</span>
<span style="color: #7E7E7E;">// Brushduino</span>
<span style="color: #7E7E7E;">//</span>
<span style="color: #7E7E7E;">//////////////////////////////////////////////////////////////////////////////</span>
<span style="color: #7E7E7E;">// Pin Assignments</span>
<span style="color: #7E7E7E;">//</span>
<span style="color: #CC6600;">int</span> analogXPin = 0;
<span style="color: #CC6600;">int</span> analogYPin = 1;
<span style="color: #CC6600;">int</span> analogZPin = 2;
<span style="color: #7E7E7E;">// Arduino indicator LED</span>
<span style="color: #CC6600;">int</span> ledPin = 13;
<span style="color: #7E7E7E;">// Activity LED Assignments</span>
<span style="color: #CC6600;">int</span> activityLED1 = 6;
<span style="color: #CC6600;">int</span> activityLED2 = 7;
<span style="color: #CC6600;">int</span> activityLED3 = 8;
<span style="color: #CC6600;">int</span> activityLED4 = 9;
<span style="color: #7E7E7E;">// Audio Pin</span>
<span style="color: #CC6600;">int</span> audioPWM = 11;
<span style="color: #CC6600;">int</span> regionLEDs[] = {3, 10, 4, 5, 12, 2};
<span style="color: #7E7E7E;">//////////////////////////////////////////////////////////////////////////////</span>
<span style="color: #7E7E7E;">// High Pass Filter Variables</span>
<span style="color: #7E7E7E;">//</span>
<span style="color: #CC6600;">float</span> rollingX = 0;
<span style="color: #CC6600;">float</span> rollingY = 0;
<span style="color: #CC6600;">float</span> rollingZ = 0;
<span style="color: #CC6600;">float</span> accelX, accelY, accelZ;
<span style="color: #7E7E7E;">//////////////////////////////////////////////////////////////////////////////</span>
<span style="color: #7E7E7E;">// Brushing Parameters</span>
<span style="color: #7E7E7E;">//</span>
<span style="color: #CC6600;">boolean</span> strokeTop = <span style="color: #CC6600;">false</span>;
<span style="color: #CC6600;">boolean</span> strokeBottom = <span style="color: #CC6600;">false</span>;
<span style="color: #CC6600;">int</span> elapsed = 0;
<span style="color: #CC6600;">int</span> lastReading = 0;
<span style="color: #CC6600;">int</span> strokeCount = 0;
<span style="color: #CC6600;">float</span> strokeMin = 10;
<span style="color: #CC6600;">float</span> strokeMax = 50;
<span style="color: #CC6600;">int</span> maxStrokeDuration = 250;
<span style="color: #CC6600;">int</span> minStrokeDuration = 50;
<span style="color: #7E7E7E;">// Number of counted strokes for each "region" of the mouth</span>
<span style="color: #CC6600;">int</span> strokesPerRegion = 60;
<span style="color: #7E7E7E;">// Iterations through the main loop</span>
<span style="color: #CC6600;">unsigned</span> <span style="color: #CC6600;">int</span> loopIterations = 0;
<span style="color: #7E7E7E;">// The rate we flash the current region</span>
<span style="color: #CC6600;">int</span> flashRate = 1000;
<span style="color: #7E7E7E;">// The region we're brushing in</span>
<span style="color: #CC6600;">int</span> curRegion = 0;
<span style="color: #7E7E7E;">//////////////////////////////////////////////////////////////////////////////</span>
<span style="color: #7E7E7E;">// Music Definitions</span>
<span style="color: #7E7E7E;">//</span>
<span style="color: #CC6600;">int</span> tempoSlow = 100;
<span style="color: #CC6600;">int</span> tempoFast = 50;
<span style="color: #7E7E7E;">//////////////////////////////////////////////////////////////////////////////</span>
<span style="color: #7E7E7E;">// setup()</span>
<span style="color: #7E7E7E;">//</span>
<span style="color: #CC6600;">void</span> <span style="color: #CC6600;"><b>setup</b></span>()
{
<span style="color: #CC6600;"><b>Serial</b></span>.<span style="color: #CC6600;">begin</span>(115200);
<span style="color: #CC6600;">pinMode</span>(ledPin, <span style="color: #006699;">OUTPUT</span>); <span style="color: #7E7E7E;">// declare the ledPin as an OUTPUT</span>
<span style="color: #CC6600;">analogReference</span>(<span style="color: #006699;">EXTERNAL</span>);
<span style="color: #7E7E7E;">// Activity LED's</span>
<span style="color: #CC6600;">pinMode</span>(activityLED1, <span style="color: #006699;">OUTPUT</span>);
<span style="color: #CC6600;">pinMode</span>(activityLED2, <span style="color: #006699;">OUTPUT</span>);
<span style="color: #CC6600;">pinMode</span>(activityLED3, <span style="color: #006699;">OUTPUT</span>);
<span style="color: #CC6600;">pinMode</span>(activityLED4, <span style="color: #006699;">OUTPUT</span>);
<span style="color: #7E7E7E;">// Audio out</span>
<span style="color: #CC6600;">pinMode</span>(audioPWM, <span style="color: #006699;">OUTPUT</span>);
<span style="color: #7E7E7E;">// Mouth Region LED's</span>
<span style="color: #CC6600;">pinMode</span>(regionLEDs[0], <span style="color: #006699;">OUTPUT</span>);
<span style="color: #CC6600;">pinMode</span>(regionLEDs[1], <span style="color: #006699;">OUTPUT</span>);
<span style="color: #CC6600;">pinMode</span>(regionLEDs[2], <span style="color: #006699;">OUTPUT</span>);
<span style="color: #CC6600;">pinMode</span>(regionLEDs[3], <span style="color: #006699;">OUTPUT</span>);
<span style="color: #CC6600;">pinMode</span>(regionLEDs[4], <span style="color: #006699;">OUTPUT</span>);
<span style="color: #CC6600;">pinMode</span>(regionLEDs[5], <span style="color: #006699;">OUTPUT</span>);
loopIterations = 0;
curRegion = 0;
<span style="color: #7E7E7E;">// After init, play the one bar intro to the song</span>
PlaySong(0, tempoSlow);
}
<span style="color: #7E7E7E;">//////////////////////////////////////////////////////////////////////////////</span>
<span style="color: #7E7E7E;">// UpdateCount()</span>
<span style="color: #7E7E7E;">//</span>
<span style="color: #7E7E7E;">// Do accelerometer stroke counting</span>
<span style="color: #7E7E7E;">//</span>
<span style="color: #CC6600;">void</span> UpdateCount()
{
<span style="color: #7E7E7E;">// A single stroke requires going below and then above a threshhold within a certain amount of time</span>
<span style="color: #7E7E7E;">//</span>
elapsed = <span style="color: #CC6600;">millis</span>();
<span style="color: #7E7E7E;">// Magnitude of 3d accelerometer reading</span>
<span style="color: #CC6600;">float</span> val = <span style="color: #CC6600;">sqrt</span>(accelX * accelX + accelY * accelY + accelZ * accelZ);
<span style="color: #7E7E7E;">// Serial.println(val);</span>
<span style="color: #7E7E7E;">// See it's been at least enough time to try and count a stroke</span>
<span style="color: #CC6600;">if</span> (elapsed > lastReading + minStrokeDuration)
{
<span style="color: #7E7E7E;">// See if we've got a stroke top</span>
<span style="color: #CC6600;">if</span> (val > strokeMax)
{
strokeTop = <span style="color: #CC6600;">true</span>;
lastReading = elapsed;
}
<span style="color: #7E7E7E;">// See if we've found the stroke bottom</span>
<span style="color: #CC6600;">if</span> (val < strokeMin)
{
strokeBottom = <span style="color: #CC6600;">true</span>;
lastReading = elapsed;
}
}
<span style="color: #7E7E7E;">// See if we failed to identify a stroke inside the maximum time window</span>
<span style="color: #CC6600;">if</span> (elapsed > lastReading + maxStrokeDuration)
{
<span style="color: #7E7E7E;">// No stroke found, reset our stroke tracking and start again</span>
strokeTop = <span style="color: #CC6600;">false</span>;
strokeBottom = <span style="color: #CC6600;">false</span>;
lastReading = elapsed;
}
<span style="color: #CC6600;">else</span> <span style="color: #7E7E7E;">// We haven't timed out our stroke yet, see if we've identified one</span>
<span style="color: #CC6600;">if</span> (strokeTop & strokeBottom)
{
<span style="color: #7E7E7E;">// Yes, both top and bottom of stroke have been found, we count this</span>
strokeCount++;
<span style="color: #7E7E7E;">// Reset stroke tracking</span>
strokeTop = <span style="color: #CC6600;">false</span>;
strokeBottom = <span style="color: #CC6600;">false</span>;
lastReading = elapsed;
<span style="color: #7E7E7E;">// Flash the led and pop the audio indicating we detected something</span>
<span style="color: #CC6600;">digitalWrite</span>(audioPWM, <span style="color: #006699;">HIGH</span>);
<span style="color: #CC6600;">digitalWrite</span>(ledPin, <span style="color: #006699;">HIGH</span>); <span style="color: #7E7E7E;">// turn the ledPin on</span>
<span style="color: #CC6600;">delay</span>(30); <span style="color: #7E7E7E;">// stop the program for some time</span>
<span style="color: #CC6600;">digitalWrite</span>(ledPin, <span style="color: #006699;">LOW</span>); <span style="color: #7E7E7E;">// turn the ledPin off</span>
<span style="color: #CC6600;">digitalWrite</span>(audioPWM, <span style="color: #006699;">LOW</span>);
}
}
<span style="color: #7E7E7E;">//////////////////////////////////////////////////////////////////////////////</span>
<span style="color: #7E7E7E;">// loop()</span>
<span style="color: #7E7E7E;">//</span>
<span style="color: #7E7E7E;">// Arduino main loop</span>
<span style="color: #7E7E7E;">//</span>
<span style="color: #CC6600;">void</span> <span style="color: #CC6600;"><b>loop</b></span>()
{
<span style="color: #CC6600;">boolean</span> flashOn = (loopIterations % flashRate) > (flashRate / 3);
<span style="color: #7E7E7E;">// Read the 3 axes analog values from the accelerometer</span>
<span style="color: #CC6600;">int</span> rawX = <span style="color: #CC6600;">analogRead</span>(analogXPin) - 512; <span style="color: #7E7E7E;">// read the value from the sensor</span>
<span style="color: #CC6600;">int</span> rawY = <span style="color: #CC6600;">analogRead</span>(analogYPin) - 512; <span style="color: #7E7E7E;">// read the value from the sensor</span>
<span style="color: #CC6600;">int</span> rawZ = <span style="color: #CC6600;">analogRead</span>(analogZPin) - 512; <span style="color: #7E7E7E;">// read the value from the sensor</span>
<span style="color: #7E7E7E;">// Our High Pass filter works better with signed floating point values</span>
<span style="color: #CC6600;">float</span> floatX = (<span style="color: #CC6600;">float</span>)rawX,
floatY = (<span style="color: #CC6600;">float</span>)rawY,
floatZ = (<span style="color: #CC6600;">float</span>)rawZ;
<span style="color: #7E7E7E;">// Low pass filter</span>
<span style="color: #CC6600;">float</span> kFilteringFactor = 0.1f;
<span style="color: #7E7E7E;">// We're keeping 90% of the rolling value and adding in 10% of the new value each</span>
<span style="color: #7E7E7E;">// time. This filters out recent values and retains historical values.</span>
rollingX = (floatX * kFilteringFactor) + (rollingX * (1.0 - kFilteringFactor));
rollingY = (floatY * kFilteringFactor) + (rollingY * (1.0 - kFilteringFactor));
rollingZ = (floatZ * kFilteringFactor) + (rollingZ * (1.0 - kFilteringFactor));
<span style="color: #7E7E7E;">// High pass filter</span>
<span style="color: #7E7E7E;">// Now we remove the historical values to emphasize current values more. The high</span>
<span style="color: #7E7E7E;">// pass filter helps us remove gravity from the reading so we can get orientation-</span>
<span style="color: #7E7E7E;">// independent acceleration values from the device</span>
accelX = floatX - rollingX;
accelY = floatY - rollingY;
accelZ = floatZ - rollingZ;
<span style="color: #7E7E7E;">// We have 4 "crawling" LED's to show progress towards each mouth region's stroke</span>
<span style="color: #7E7E7E;">// count</span>
<span style="color: #CC6600;">int</span> interval = 1;
<span style="color: #CC6600;">int</span> val = strokeCount % (interval * 4);
<span style="color: #7E7E7E;">// Stroke LED's are turned on to indicate progress towards goal</span>
<span style="color: #CC6600;">if</span> (val >= interval * 0 && val < interval * 1) <span style="color: #CC6600;">digitalWrite</span>(activityLED1, <span style="color: #006699;">HIGH</span>); <span style="color: #CC6600;">else</span> <span style="color: #CC6600;">digitalWrite</span>(activityLED1, <span style="color: #006699;">LOW</span>);
<span style="color: #CC6600;">if</span> (val >= interval * 1 && val < interval * 2) <span style="color: #CC6600;">digitalWrite</span>(activityLED2, <span style="color: #006699;">HIGH</span>); <span style="color: #CC6600;">else</span> <span style="color: #CC6600;">digitalWrite</span>(activityLED2, <span style="color: #006699;">LOW</span>);
<span style="color: #CC6600;">if</span> (val >= interval * 2 && val < interval * 3) <span style="color: #CC6600;">digitalWrite</span>(activityLED3, <span style="color: #006699;">HIGH</span>); <span style="color: #CC6600;">else</span> <span style="color: #CC6600;">digitalWrite</span>(activityLED3, <span style="color: #006699;">LOW</span>);
<span style="color: #CC6600;">if</span> (val >= interval * 3 && val < interval * 4) <span style="color: #CC6600;">digitalWrite</span>(activityLED4, <span style="color: #006699;">HIGH</span>); <span style="color: #CC6600;">else</span> <span style="color: #CC6600;">digitalWrite</span>(activityLED4, <span style="color: #006699;">LOW</span>);
<span style="color: #7E7E7E;">// Region LED's are turned on to tell the user which area of the mouth to brush</span>
<span style="color: #7E7E7E;">// at any point in time. We start with region 1 and are done when all 6 have</span>
<span style="color: #7E7E7E;">// been on long enough.</span>
<span style="color: #7E7E7E;">// Iterate through regions</span>
<span style="color: #CC6600;">for</span> (<span style="color: #CC6600;">int</span> region = 0; region <= 6; region++)
{
<span style="color: #CC6600;">if</span> (strokeCount > strokesPerRegion * region)
{
<span style="color: #7E7E7E;">// Flash the currently active region</span>
<span style="color: #CC6600;">digitalWrite</span>(regionLEDs[region], (flashOn || (region < curRegion-1)) ? <span style="color: #006699;">HIGH</span> : <span style="color: #006699;">LOW</span>);
<span style="color: #7E7E7E;">// See if we're ready to move to the next region</span>
<span style="color: #CC6600;">if</span> (region == curRegion)
{
<span style="color: #CC6600;">if</span> (region > 0)
{
PlaySong(region + 1, tempoSlow);
}
curRegion++;
}
}
<span style="color: #7E7E7E;">// Turn off leds for all regions not yet handled</span>
<span style="color: #CC6600;">if</span> (region >= curRegion)
{
<span style="color: #CC6600;">digitalWrite</span>(regionLEDs[region], <span style="color: #006699;">LOW</span>);
}
}
<span style="color: #7E7E7E;">// All finished? Have a little "you're all done" party</span>
<span style="color: #CC6600;">if</span> (curRegion == 7)
{
curRegion++;
PlaySong(1, tempoFast);
PlaySong(2, tempoFast);
PlaySong(3, tempoFast);
PlaySong(4, tempoFast);
PlaySong(5, tempoFast);
PlaySong(6, tempoFast);
<span style="color: #CC6600;">int</span> i;
<span style="color: #CC6600;">int</span> j;
<span style="color: #CC6600;">for</span> (j=0; j<6; j++)
{
<span style="color: #CC6600;">for</span> (<span style="color: #CC6600;">int</span> i=0; i<6; i++)
{
<span style="color: #CC6600;">digitalWrite</span>(regionLEDs[i], <span style="color: #006699;">HIGH</span>);
}
<span style="color: #CC6600;">delay</span>(250);
<span style="color: #CC6600;">for</span> (<span style="color: #CC6600;">int</span> i=0; i<6; i++)
{
<span style="color: #CC6600;">digitalWrite</span>(regionLEDs[i], <span style="color: #006699;">LOW</span>);
}
<span style="color: #CC6600;">delay</span>(250);
}
}
<span style="color: #7E7E7E;">// Count brush strokes </span>
UpdateCount();
<span style="color: #7E7E7E;">// Count loop iterations for flashing things</span>
loopIterations++;
}
<span style="color: #7E7E7E;">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</span>
<span style="color: #7E7E7E;">//</span>
<span style="color: #7E7E7E;">// freqout borrowed from Paul Badger, thanks Paul!</span>
<span style="color: #7E7E7E;">//</span>
<span style="color: #7E7E7E;">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</span>
<span style="color: #7E7E7E;">/* freqout(freq, t) // freq in hz, t in ms</span>
<span style="color: #7E7E7E;">* Paul Badger 2007</span>
<span style="color: #7E7E7E;">* a simple tone generation function</span>
<span style="color: #7E7E7E;">* generates square waves of arbitrary frequency and duration</span>
<span style="color: #7E7E7E;">* program also includes a top-octave lookup table & transposition function</span>
<span style="color: #7E7E7E;">*/</span>
#include <math.h> <span style="color: #7E7E7E;">// requires an Atmega168 chip </span>
#define outpin audioPWM <span style="color: #7E7E7E;">// audio out to speaker or amp</span>
<span style="color: #7E7E7E;">// note values for two octave scale</span>
<span style="color: #7E7E7E;">// divide them by powers of two to generate other octaves</span>
<span style="color: #CC6600;">float</span> A = 14080;
<span style="color: #CC6600;">float</span> AS = 14917.2;
<span style="color: #CC6600;">float</span> B = 15804.3;
<span style="color: #CC6600;">float</span> C = 16744;
<span style="color: #CC6600;">float</span> CS = 17739.7;
<span style="color: #CC6600;">float</span> D = 18794.5;
<span style="color: #CC6600;">float</span> DS = 19912.1;
<span style="color: #CC6600;">float</span> E = 21096.2;
<span style="color: #CC6600;">float</span> F = 22350.6;
<span style="color: #CC6600;">float</span> FS = 23679.6;
<span style="color: #CC6600;">float</span> G = 25087.7;
<span style="color: #CC6600;">float</span> GS = 26579.5;
<span style="color: #CC6600;">float</span> A2 = 28160;
<span style="color: #CC6600;">float</span> A2S = 29834.5;
<span style="color: #CC6600;">float</span> B2 = 31608.5;
<span style="color: #CC6600;">float</span> C2 = 33488.1;
<span style="color: #CC6600;">float</span> C2S = 35479.4;
<span style="color: #CC6600;">float</span> D2 = 37589.1;
<span style="color: #CC6600;">float</span> D2S = 39824.3;
<span style="color: #CC6600;">float</span> E2 = 42192.3;
<span style="color: #CC6600;">float</span> F2 = 44701.2;
<span style="color: #CC6600;">float</span> F2S = 47359.3;
<span style="color: #CC6600;">float</span> G2 = 50175.4;
<span style="color: #CC6600;">float</span> G2S = 53159;
<span style="color: #CC6600;">float</span> A3 = 56320;
<span style="color: #CC6600;">float</span> AS3 = 59669;
<span style="color: #CC6600;">float</span> B3 = 63217;
<span style="color: #CC6600;">float</span> C3 = 66976.2;
<span style="color: #CC6600;">float</span> REST = 0;
<span style="color: #7E7E7E;">// freqout</span>
<span style="color: #7E7E7E;">//</span>
<span style="color: #7E7E7E;">// Generate the tone</span>
<span style="color: #7E7E7E;">//</span>
<span style="color: #CC6600;">void</span> freqout(<span style="color: #CC6600;">int</span> freq, <span style="color: #CC6600;">int</span> t) <span style="color: #7E7E7E;">// freq in hz, t in ms</span>
{
<span style="color: #7E7E7E;">// Added special handling for rests (avoids pops)</span>
<span style="color: #CC6600;">if</span> (freq == 0)
{
<span style="color: #CC6600;">delay</span>(t);
<span style="color: #CC6600;">return</span>;
}
<span style="color: #CC6600;">int</span> hperiod; <span style="color: #7E7E7E;">//calculate 1/2 period in us</span>
<span style="color: #CC6600;">long</span> cycles, i;
<span style="color: #CC6600;">pinMode</span>(outpin, <span style="color: #006699;">OUTPUT</span>); <span style="color: #7E7E7E;">// turn on output pin</span>
hperiod = (500000 / freq) - 7; <span style="color: #7E7E7E;">// subtract 7 us to make up for digitalWrite overhead</span>
cycles = ((<span style="color: #CC6600;">long</span>)freq * (<span style="color: #CC6600;">long</span>)t) / 1000; <span style="color: #7E7E7E;">// calculate cycles</span>
<span style="color: #CC6600;">for</span> (i=0; i<= cycles; i++)
{
<span style="color: #7E7E7E;">// play note for t ms </span>
<span style="color: #CC6600;">digitalWrite</span>(outpin, <span style="color: #006699;">HIGH</span>);
<span style="color: #CC6600;">delayMicroseconds</span>(hperiod);
<span style="color: #CC6600;">digitalWrite</span>(outpin, <span style="color: #006699;">LOW</span>);
<span style="color: #CC6600;">delayMicroseconds</span>(hperiod - 1); <span style="color: #7E7E7E;">// - 1 to make up for digitaWrite overhead</span>
}
<span style="color: #CC6600;">pinMode</span>(outpin, <span style="color: #006699;">INPUT</span>); <span style="color: #7E7E7E;">// shut off pin to avoid noise from other operations</span>
}
<span style="color: #CC6600;">float</span> EIGHTH = 1;
<span style="color: #CC6600;">float</span> DOTTED_EIGHTH = 1.5;
<span style="color: #CC6600;">float</span> QUARTER = 2;
<span style="color: #CC6600;">float</span> DOTTED_QUARTER =3;
<span style="color: #CC6600;">float</span> HALF = 4;
<span style="color: #CC6600;">float</span> WHOLE = 8;
<span style="color: #CC6600;">float</span> ETERNITY =-1;
<span style="color: #7E7E7E;">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</span>
<span style="color: #7E7E7E;">//</span>
<span style="color: #7E7E7E;">// My Mario Music</span>
<span style="color: #7E7E7E;">//</span>
<span style="color: #7E7E7E;">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</span>
<span style="color: #CC6600;">int</span> cNumSongs = 7;
<span style="color: #CC6600;">float</span> song0[] =
{
E2,EIGHTH, E2,QUARTER, E2,EIGHTH, REST,EIGHTH, C2,EIGHTH, E2,QUARTER, G2,HALF, G,HALF,
REST,ETERNITY
};
<span style="color: #CC6600;">float</span> song1[] =
{
C2,DOTTED_QUARTER, G,EIGHTH, REST,QUARTER, E,QUARTER, REST,EIGHTH, A2,QUARTER, B2,EIGHTH, REST,EIGHTH, A2S,EIGHTH, A2,QUARTER,
G,DOTTED_EIGHTH, E2,DOTTED_EIGHTH, G2,EIGHTH, A3,QUARTER, F2,EIGHTH, G2,EIGHTH, REST,EIGHTH, E2,QUARTER, C2,EIGHTH, D2,EIGHTH, B2,DOTTED_QUARTER,
REST,ETERNITY
};
<span style="color: #CC6600;">float</span> song2[] =
{
C2,DOTTED_QUARTER, G,EIGHTH, REST,QUARTER, E,QUARTER, REST,EIGHTH, A2,QUARTER, B2,EIGHTH, REST,EIGHTH, A2S,EIGHTH, A2,QUARTER,
G,DOTTED_EIGHTH, E2,DOTTED_EIGHTH, G2,EIGHTH, A3,QUARTER, F2,EIGHTH, G2,EIGHTH, REST,EIGHTH, E2,QUARTER, C2,EIGHTH, D2,EIGHTH, B2,DOTTED_QUARTER,
REST,ETERNITY
};
<span style="color: #CC6600;">float</span> song3[] =
{
REST,QUARTER, G2,EIGHTH, F2S,EIGHTH, F2,EIGHTH, D2S,QUARTER, E2,EIGHTH, REST,EIGHTH, GS,EIGHTH, A2,EIGHTH, C2,EIGHTH, REST,EIGHTH, A2,EIGHTH, C2,EIGHTH, D2,EIGHTH,
REST,QUARTER, G2,EIGHTH, F2S,EIGHTH, F2,EIGHTH, D2S,QUARTER, E2,EIGHTH, REST,EIGHTH, C3,QUARTER, C3,EIGHTH, C3,HALF,
REST,ETERNITY
};
<span style="color: #CC6600;">float</span> song4[] =
{
REST,QUARTER, G2,EIGHTH, F2S,EIGHTH, F2,EIGHTH, D2S,QUARTER, E2,EIGHTH, REST,EIGHTH, GS,EIGHTH, A2,EIGHTH, C2,EIGHTH, REST,EIGHTH, A2,EIGHTH, C2,EIGHTH, D2,EIGHTH,
REST,QUARTER, D2S,QUARTER, REST,EIGHTH, D2,DOTTED_QUARTER, C2,HALF, REST,HALF,
REST,ETERNITY
};
<span style="color: #CC6600;">float</span> song5[] =
{
C2,EIGHTH, C2,QUARTER, C2,EIGHTH, REST,EIGHTH, C2,EIGHTH, D2,QUARTER, E2,EIGHTH, C2,QUARTER, A2,EIGHTH, G,HALF,
C2,EIGHTH, C2,QUARTER, C2,EIGHTH, REST,EIGHTH, C2,EIGHTH, D2,EIGHTH, E2,EIGHTH, REST,WHOLE,
REST,ETERNITY
};
<span style="color: #CC6600;">float</span> song6[] =
{
C2,EIGHTH, C2,QUARTER, C2,EIGHTH, REST,EIGHTH, C2,EIGHTH, D2,QUARTER, E2,EIGHTH, C2,QUARTER, A2,EIGHTH, G,HALF,
E2,EIGHTH, E2,QUARTER, E2,EIGHTH, REST,EIGHTH, C2,EIGHTH, E2,QUARTER, G2,QUARTER, REST, HALF,
REST,ETERNITY
};
<span style="color: #CC6600;">float</span>* songs[] =
{
song0,
song1,
song2,
song3,
song4,
song5,
song6,
};
<span style="color: #7E7E7E;">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</span>
<span style="color: #7E7E7E;">// PlaySong()</span>
<span style="color: #7E7E7E;">//</span>
<span style="color: #7E7E7E;">// Just a little function to play music and light LED's</span>
<span style="color: #7E7E7E;">//</span>
<span style="color: #CC6600;">void</span> PlaySong(<span style="color: #CC6600;">int</span> songIndex, <span style="color: #CC6600;">int</span> tempo)
{
<span style="color: #CC6600;">if</span> (songIndex < 0 || songIndex >= cNumSongs)
{
<span style="color: #CC6600;">return</span>;
}
<span style="color: #7E7E7E;">// Serial.println("PlaySong");</span>
<span style="color: #CC6600;">float</span>* song = songs[songIndex];
<span style="color: #CC6600;">int</span> x;
<span style="color: #CC6600;">for</span>(x= 0; x<10000; x=x+2)
{
<span style="color: #CC6600;">int</span> noteval = (<span style="color: #CC6600;">int</span>)(song[x] / 64.0f);
<span style="color: #CC6600;">int</span> dur = (<span style="color: #CC6600;">int</span>)((<span style="color: #CC6600;">float</span>)tempo * song[x+1]);
<span style="color: #CC6600;">if</span>(dur < 0)
<span style="color: #CC6600;">break</span>;
freqout(noteval, dur);
<span style="color: #CC6600;">for</span> (<span style="color: #CC6600;">int</span> i=0; i<6; i++)
{
<span style="color: #CC6600;">boolean</span> ledOn = (i == (<span style="color: #CC6600;">millis</span>() % 6));
<span style="color: #CC6600;">digitalWrite</span>(regionLEDs[i], ledOn ? <span style="color: #006699;">HIGH</span> : <span style="color: #006699;">LOW</span>);
}
<span style="color: #CC6600;">delay</span>(10);
}
}
</pre>Stevehttp://www.blogger.com/profile/14070951525184172272noreply@blogger.com4tag:blogger.com,1999:blog-2410889582352367061.post-8061615777151872952009-03-24T11:46:00.000-07:002010-02-21T14:51:06.858-08:00Happy Ada Lovelace Day!From PedgeBank:<br/><br/><a href="http://www.pledgebank.com/AdaLovelaceDay">http://www.pledgebank.com/AdaLovelaceDay</a><br/><br/>Ada Lovelace Day is an international day of blogging to draw attention to women excelling in technology.<br/><br/>Women's contributions often go unacknowledged, their innovations seldom mentioned, their faces rarely recognised. We want you to tell the world about these unsung heroines. Whatever she does, whether she is a sysadmin or a tech entrepreneur, a programmer or a designer, developing software or hardware, a tech journalist or a tech consultant, we want to celebrate her achievements.<br/><br/>It doesn't matter how new or old your blog is, what gender you are, what language you blog in, or what you normally blog about - everyone is invited to take part. All you need to do is sign up to this pledge and then publish your blog post any time on Tuesday 24th March 2009. If you're going to be away that day, feel free to write your post in advance and set your blogging system to publish it that day. We will gather as many of the posts together on the day as we can, and we'll let you know exactly how we're going to do that nearer the time.<br/><br/>For ongoing updates about Ada Lovelace day, please follow us on Twitter, join our mailing list or see our blog.<br/><br/>http://findingada.com/<br/><br/>http://twitter.com/FindingAda<br/><br/>http://groups.yahoo.com/group/findingada<br/><br/><strong> Who was Ada? </strong><br/><blockquote>Ada Lovelace was one of the world's first computer programmers, and one of the first people to see computers as more than just a machine for doing sums. She wrote programmes for Charles Babbage's Analytical Engine, a general-purpose computing machine, despite the fact that it was never built. She also wrote the very first description of a computer and of software. Anything wrong with this pledge? Tell us!</blockquote>Stevehttp://www.blogger.com/profile/14070951525184172272noreply@blogger.com0tag:blogger.com,1999:blog-2410889582352367061.post-51484288917990196822007-12-04T12:03:00.000-08:002010-02-21T14:51:06.839-08:00Lucky's Beepy Ball II!<strong>UPDATE</strong>! Scroll to the bottom to see the results of the first trial run!<br/><br/>My dog is blind. Well, mostly blind---he can see a few feet and light and dark---but for most intents and purposes, he's blind. He's not blind in old age, but blind congenitally---he's only 3. His name is Lucky. As a golden retriever, he's obsessed with getting, keeping, carrying, fetching a ball shaped object of any sort. I set out to make a ball that beeps that he can find easily since his hearing is very acute now that he's been fully blind for a while.<br/><br/>I scratched my original design for the Lucky Beepy Ball that was built around a LM556 timer chip and a handful of components (four resistors, two capacitors, and two signal transistors) as being a little too heavyweight for putting inside a ball. I did a lot of head scratching, reading, and doing other builds to learn more and finally settled on a very simple design: 1 ATtiny13V microcontroller, one piezo speaker, a small battery, and a switch. You can't get too much simpler than that.<br/><br/>The Atmel ATtiny13V was PERFECT for this job, as it had a low pin count (it's an 8 pin ATtiny) and operated well in a wide range of voltages. It can operate normally at between 1.8v and 5.5v (the 'V' model of the ATtiny13 is the low voltage version) and is plenty fast (I run mine at 4.8MHz on the internal oscillator). Best of all, it can source and sink at least 20mA on its digital output pins, and has a nice 8 bit timer built in that is easy to program for interesting bleepy sounds.<br/><br/>First I prototyped my design on a small piece of breadboard. All the ATtiny13V REALLY needs is the Vcc connection on pin 8, the GND connection on pin 4, and the two legs of the piezo speaker on pins 2 and 3, but I used the breadboard as my programming harness as well so you can see the 6 pin ISP header at the top. It took a little experimentation to get the beep sound the way I wanted it.<br/><br/>I wanted a beep sound that was easily audible by a dog under a lot of conditions. I figured a chirp would probably work the best. It would start at a high frequency above human hearing but dog-audible, and then decrease in frequency over time until it got low enough so that the wavelength was long enough to have good travel properties through tall grass. Long wavelength sound travels greater distances and can pass through solid objects better than short wavelength sound, so I wanted to take advantage of this property. I wanted alternating periods of chirping and silence so that it was easier for Lucky to triangulate the position of the sound. With a constant chirping, I was concerned that the sound reflection would interfere with his ability to locate the source.<br/><br/><a href="http://camelpunch.files.wordpress.com/2007/12/20071126110347833_1_original.jpg" title="20071126110347833_1_original.jpg"><img src="http://camelpunch.files.wordpress.com/2007/12/20071126110347833_1_original.thumbnail.jpg" alt="20071126110347833_1_original.jpg" /></a><br/><br/>Here are the parts all laid out and ready to assemble. This build was going to be free-formed (point to point wiring) instead of boarded on a piece of experimenters board/veroboard since it needs to be compact and fit inside a ball or Kong ball of some kind.<br/><br/><a href="http://camelpunch.files.wordpress.com/2007/12/20071126110347833_2_original.jpg" title="20071126110347833_2_original.jpg"><img src="http://camelpunch.files.wordpress.com/2007/12/20071126110347833_2_original.thumbnail.jpg" alt="20071126110347833_2_original.jpg" /></a><br/><br/>After programming the ATtiny13V with my chirpy sound code, I ruthlessly hacked its legs off with a wire nipper. This was surprisingly painful for me to do... there's something about defacing a MCU that physically hurts. I wanted unused pins to be out of the way to reduce the possibility of a short and to keep them from interfering with other parts as I put everything together.<br/><br/><a href="http://camelpunch.files.wordpress.com/2007/12/20071126110347833_3_original.jpg" title="20071126110347833_3_original.jpg"><img src="http://camelpunch.files.wordpress.com/2007/12/20071126110347833_3_original.thumbnail.jpg" alt="20071126110347833_3_original.jpg" /></a><br/><br/>The battery I'm using is a 2.4v NiMH battery that I salvaged out of a tiny radio controlled car (one of those Hot Wheels-sized radio control cars that you dock with the transmitter to charge it.) I hadn't used the radio control car much before it broke, so I took it all apart and saved a few select pieces from it. This battery only stores 70mAh worth of charge, but then I don't anticipate that the ATtiny13V and the piezo are going to really need all that much. Plus it was the perfect size. I soldered right onto it at each end.<br/><br/><a href="http://camelpunch.files.wordpress.com/2007/12/20071126110347833_4_original.jpg" title="20071126110347833_4_original.jpg"><img src="http://camelpunch.files.wordpress.com/2007/12/20071126110347833_4_original.thumbnail.jpg" alt="20071126110347833_4_original.jpg" /></a><br/><br/>I brought the positive lead from the "bottom" of the battery up to the center pole on the SPDT switch so I can turn this thing off when we're done playing ball. I soldered the switch's metal housing directly to the negative side of the battery by using a little liquid solder flux (I have a solder flux pen I use for things like this) to get everything to stick.<br/><br/><a href="http://camelpunch.files.wordpress.com/2007/12/20071126110347833_5_original.jpg" title="20071126110347833_5_original.jpg"><img src="http://camelpunch.files.wordpress.com/2007/12/20071126110347833_5_original.thumbnail.jpg" alt="20071126110347833_5_original.jpg" /></a><br/><br/>Next, I mounted the ATtiny13V directly on the switch, soldering the Vcc pin (pin 8) directly to one side of the switch. Then I soldered the GND pin (pin 4) directly to the metal housing. Pins 2 and 3 that you can see in the right hand picture are going to be wired up to the piezo speaker.<br/><br/><a href="http://camelpunch.files.wordpress.com/2007/12/20071126110347833_6_original.jpg" title="20071126110347833_6_original.jpg"><img src="http://camelpunch.files.wordpress.com/2007/12/20071126110347833_6_original.thumbnail.jpg" alt="20071126110347833_6_original.jpg" /></a><br/><br/>Here the speaker is wired to the MCU and the wiring is done.<br/><br/><a href="http://camelpunch.files.wordpress.com/2007/12/20071126110347833_7_original.jpg" title="20071126110347833_7_original.jpg"><img src="http://camelpunch.files.wordpress.com/2007/12/20071126110347833_7_original.thumbnail.jpg" alt="20071126110347833_7_original.jpg" /></a><br/><br/>Now it's time to hot glue this mess to make it more shock resistant and to keep everything in place. I'm using a typical craft hot glue gun to turn this all into a big capsule shaped insert that I can put inside a "Kong" brand dog toy to play fetch with.<br/><br/><a href="http://camelpunch.files.wordpress.com/2007/12/20071126110347833_8_original.jpg" title="20071126110347833_8_original.jpg"><img src="http://camelpunch.files.wordpress.com/2007/12/20071126110347833_8_original.thumbnail.jpg" alt="20071126110347833_8_original.jpg" /></a><br/><br/>... to be continued ...<br/><h3> <a name='more'></a><strong>*</strong><strong>UPDATE*</strong></h3><br/>Ok, today's December 1st, and I took the Luckyball out for a test run. Results were VERY promising!<br/><br/>I needed to hot glue it into a capsule shape for embedding in something like this:<br/><br/><a href="http://camelpunch.files.wordpress.com/2007/12/20071126110347833_9.gif" title="20071126110347833_9.gif"><img src="http://camelpunch.files.wordpress.com/2007/12/20071126110347833_9.gif" alt="20071126110347833_9.gif" /></a><br/><br/>We have a Kong treat ball (not the one pictured) on hand that was perfect for a test run.<br/><br/>I made a cylindrical form to hold the glue that was slightly larger than the diameter of the device (the widest part across the device was the piezo speaker) and put a little hot glue into the bottom of it.<br/><br/><a href="http://camelpunch.files.wordpress.com/2007/12/20071126110347833_10_original.jpg" title="20071126110347833_10_original.jpg"><img src="http://camelpunch.files.wordpress.com/2007/12/20071126110347833_10_original.thumbnail.jpg" alt="20071126110347833_10_original.jpg" /></a><br/><br/>Then I put the device inside and filled it to the brim, giving it time to run everywhere around the device and coat it on all sides. I did only a passable job at this, as I discovered later. The main thing was to make it shock resistant and waterproof.<br/><br/>I left the two charging wires sticking out the top and when the hot glue was cool, I snipped the ends to prevent shorting out in dog saliva which was surely going to be the largest environmental hazard next to outright breaking from shock damage.<br/><br/>I also used needle-nosed pliers and a jeweler's screwdriver to dig out the switch on either side so I could throw it back and forth. It needed a little room to travel to turn the device on and off.<br/><br/>I turned it on and jammed in into the Kong treat ball where it fit very snugly and stayed put for the whole hike.<br/><br/>Then we went on a long hike and threw the ball a lot.<br/><br/>Here's what it looked like when we got back home and I pulled it out:<br/><br/><a href="http://camelpunch.files.wordpress.com/2007/12/20071126110347833_11_original.jpg" title="20071126110347833_11_original.jpg"><img src="http://camelpunch.files.wordpress.com/2007/12/20071126110347833_11_original.thumbnail.jpg" alt="20071126110347833_11_original.jpg" /></a><br/><br/><a href="http://camelpunch.files.wordpress.com/2007/12/20071126110347833_12_original.jpg" title="20071126110347833_12_original.jpg"><img src="http://camelpunch.files.wordpress.com/2007/12/20071126110347833_12_original.thumbnail.jpg" alt="20071126110347833_12_original.jpg" /></a><br/>A little worse for wear, but still intact!<br/><br/>In fact, my estimated current draw was about 30mAh from the ATtiny13V and the piezo speaker driven directly from the digital outputs. The battery was rated at 70mAh, so I figured I'd get about an hour out of it before it started to fade and that's just about what we got.<br/><br/>When it finally was silent, it had shorted out from slobber---though the sound intensity had started to fade noticeably at that point. We let Lucky keep the ball and he played with it for a while---dropping it and rolling it and picking it up and bouncing it and so on. It was loud enough for him to find it if it took a bad bounce, but not loud enough to locate in the open field.<br/><br/>It was amazing, though. I can't describe the feeling of watching him track it down and pick it up in a place he'd NEVER normally be able to get it. It reminded me a lot of when he was a puppy and could still see out of one eye. There were times when it was too loud from wind or crunchy leaves underfoot that he needed a little hinting (walking towards it a few feet would usually get him oriented) but for the most part he was able to find it much more quickly.<br/><br/>With some training and getting used to using his ears more, he'll get better and better. For a trial run of the first prototype, however, I'm incredibly satisfied. ·Stevehttp://www.blogger.com/profile/14070951525184172272noreply@blogger.com0tag:blogger.com,1999:blog-2410889582352367061.post-42021750373899391302007-12-04T11:57:00.000-08:002010-02-21T14:51:06.830-08:00Spooky Halloween Light DimmerHere's a quickie image gallery of my Halloween Door Light Dimmer system I cobbled together for a spooky Halloween gag.<br/><br/>The basic idea is that I'd use a distance sensor to spot people walking up the sidewalk to my house and slowly dim the lights as they get closer and closer. When they're standing there at the door, I wanted them to be surrounded by almost-darkness with the white christmas lights flickering dimly while I handed out candy.<br/><br/>To achieve this effect, I knew I'd need a reliable distance sensor that could spot a humanoid/child up to 20 feet away and then I'd need some way to control lights running off of AC current.<br/><br/>I sought out the MaxBotics MaxSonar EZ-1 board to handle the distance sensing (<a href="http://camelpunch.wordpress.com/wp-admin/if%28confirm%28%27http://www.maxbotix.com/MaxSonar-EZ1__FAQ.html%5Cn%5CnThis%20file%20was%20not%20retrieved%20because%20it%20was%20filtered%20out%20by%20your%20project%20settings.%5Cn%5CnWould%20you%20like%20to%20open%20it%20from%20the%20server?%27%29%29window.location=%27http://www.maxbotix.com/MaxSonar-EZ1__FAQ.html%27">http://www.maxbotix.com/MaxSonar-EZ1__FAQ.html</a>). It's a clever single-board controller for a 40kHz ultrasonic transducer. It uses a single-transducer model rather than the two-sensor style of Devantech's. I've never used a Devantech sensor, but the MaxBotics model fit my budget and was carried by SparkFun, so I ordered it up.<br/><br/>The controller board supports three different output formats for distance sensing information: Serial, PWM, and analog. I chose to use the analog output and the ATmega8's built-in ADC to get my distance information.<br/><br/><a href="http://camelpunch.files.wordpress.com/2007/12/20071102102103855_1_original.jpg" title="20071102102103855_1_original.jpg"><img src="http://camelpunch.files.wordpress.com/2007/12/20071102102103855_1_original.thumbnail.jpg" alt="20071102102103855_1_original.jpg" /></a><br/><br/>Here are the subsystems, labelled for your protection.<br/><br/><a href="http://camelpunch.files.wordpress.com/2007/12/20071102102103855_2_original.jpg" title="20071102102103855_2_original.jpg"><img src="http://camelpunch.files.wordpress.com/2007/12/20071102102103855_2_original.thumbnail.jpg" alt="20071102102103855_2_original.jpg" /></a><br/><br/>Here's the outlet box I built. With the help of the guy at Pini's Hardware here in town, I got it up to building code as well as getting it functional. It's four separate lines on the four outlets.<br/><br/>There was something extremely satisfying about labeling the outlets "BIT 0" and "BIT1" and so on. They were just bits on one of the ATmega8's output ports!<br/><br/><a href="http://camelpunch.files.wordpress.com/2007/12/20071102102103855_3_original.jpg" title="20071102102103855_3_original.jpg"><img src="http://camelpunch.files.wordpress.com/2007/12/20071102102103855_3_original.thumbnail.jpg" alt="20071102102103855_3_original.jpg" /></a><br/>Outlet Box<br/><br/>For controlling the lights, I checked out some options out there for controlling house current from TTL that use triacs and optocouplers. One of the better ones I found was the SEMITONE "Open Dimmer" project. <a href="http://camelpunch.wordpress.com/wp-admin/if%28confirm%28%27http://semitone.sourceforge.net/wiki/index.php/Main_Page%5Cn%5CnThis%20file%20was%20not%20retrieved%20because%20it%20was%20filtered%20out%20by%20your%20project%20settings.%5Cn%5CnWould%20you%20like%20to%20open%20it%20from%20the%20server?%27%29%29window.location=%27http://semitone.sourceforge.net/wiki/index.php/Main_Page%27">http://semitone.sourceforge.net/wiki/index.php/Main_Page</a><br/><br/>Rather than take chances on my first foray into house current, though, I opted to buy a pre-made board. One of my favorite electronics suppliers, Futurlec, had a great board they made themselves. It was cheap at $25.<br/><br/><a href="http://camelpunch.wordpress.com/wp-admin/if%28confirm%28%27http://www.futurlec.com/AC_Opto_Output_4.shtml%5Cn%5CnThis%20file%20was%20not%20retrieved%20because%20it%20was%20filtered%20out%20by%20your%20project%20settings.%5Cn%5CnWould%20you%20like%20to%20open%20it%20from%20the%20server?%27%29%29window.location=%27http://www.futurlec.com/AC_Opto_Output_4.shtml%27">http://www.futurlec.com/AC_Opto_Output_4.shtml</a><br/><br/>I doubted I could make one as cheaply and the construction seemed very solid and had just what I needed. It's driven by TTL signals and has two separate connectors for interfacing to your uC board. It's optically isolated, fuse-protected, and uses screw terminals for my AC lines. Perfect!<br/><br/><a href="http://camelpunch.files.wordpress.com/2007/12/20071102102103855_4_original.jpg" title="20071102102103855_4_original.jpg"><img src="http://camelpunch.files.wordpress.com/2007/12/20071102102103855_4_original.thumbnail.jpg" alt="20071102102103855_4_original.jpg" /></a><a href="http://camelpunch.files.wordpress.com/2007/12/20071102102103855_1_original.jpg" title="20071102102103855_1_original.jpg"><br/></a><br/><br/>Relay Board<br/><br/>Here's a picture of the MaxBotics sonar range finder, on the left, and the 8 LED debugging output device on the right. I plug a ribbon cable with 8 SMD LED's with 1k SMD current limiting resistors wired to common ground with one LED per bit on PORTB of the ATmega8. I write to these bits to help debug things.<br/><br/><a href="http://camelpunch.files.wordpress.com/2007/12/20071102102103855_5_original.jpg" title="20071102102103855_5_original.jpg"><img src="http://camelpunch.files.wordpress.com/2007/12/20071102102103855_5_original.thumbnail.jpg" alt="20071102102103855_5_original.jpg" /></a><br/><br/>Here's a closeup of the transducer:<br/><br/><a href="http://camelpunch.files.wordpress.com/2007/12/20071102102103855_6_original.jpg" title="20071102102103855_6_original.jpg"><img src="http://camelpunch.files.wordpress.com/2007/12/20071102102103855_6_original.thumbnail.jpg" alt="20071102102103855_6_original.jpg" /></a><br/><br/>Here's the ATmega8 controller board I use for most of my projects. Click on it for the Really Big version.<br/><br/><a href="http://camelpunch.files.wordpress.com/2007/12/20071102102103855_7_original.jpg" title="20071102102103855_7_original.jpg"><img src="http://camelpunch.files.wordpress.com/2007/12/20071102102103855_7_original.thumbnail.jpg" alt="20071102102103855_7_original.jpg" /></a><br/><br/>And here it is again with ports labelled.<br/><br/><a href="http://camelpunch.files.wordpress.com/2007/12/20071102102103855_8_original.jpg" title="20071102102103855_8_original.jpg"><img src="http://camelpunch.files.wordpress.com/2007/12/20071102102103855_8_original.thumbnail.jpg" alt="20071102102103855_8_original.jpg" /></a><br/><br/>Because I got started late, I had to do the build in 2 days (actually two evenings, and one morning) and got it working Halloween morning at 9:45am--just in time to scoot off to work.<br/><br/>I think it was a big success. My Halloween guests were suitably baffled by the inexplicably dimming and flashing lights and it created a great atmosphere for handing out treats.<br/><br/>...and I didn't manage to burn the house down or sustain a filling-rattling electric shock in the process. Always a plus! ·Stevehttp://www.blogger.com/profile/14070951525184172272noreply@blogger.com0tag:blogger.com,1999:blog-2410889582352367061.post-90900097509779802762007-12-04T11:49:00.000-08:002010-02-21T14:51:06.819-08:00Pumpkinlight!I put together a simple AVR-based device to stand in for the tried-and-true pumpkin candle this year. It uses two high-output (12,000 mcd) white LED's driven (a little too hard) by a regulated 5v supply that's shared with an ATtiny13v. All of this runs off of a 9v battery and should last for days given the tiny amount of current it draws.<br/><br/>The bill of materials isn't super long, and I had everything on hand so putting it together was pretty easy. I free-formed the first one, wrote the AVR Studio assembly code, then went back and made a proper schematic and built the second one. The first one is a lot uglier than the second due to all the rework and the extra wiring for the ISP connection.<br/><br/>C1 10uF<br/>C2 100uF<br/>G1 AB9V<br/>IC1 ATTINY13V-10PU<br/>IC2 LMS8117AMP-ADJ<br/>LED1 High output white 5mm<br/>LED2 High output white 5mm<br/>R1 150<br/>R2 470<br/>R3 120<br/>R4 120<br/>R5 10k This is a 10k for a pull-up on the RESET pin<br/>S1 Small SPDT sliding switch<br/>T1 2N3904 Any small signal transistor will do<br/>T2 2N3904 I used the 2N3904 because I have a big bag of them<br/><br/>Here are all of the materials required, assembled in marching order:<br/><br/><a href="http://camelpunch.files.wordpress.com/2007/12/20071018173736317_1_original.jpg" title="20071018173736317_1_original.jpg"><img src="http://camelpunch.files.wordpress.com/2007/12/20071018173736317_1_original.thumbnail.jpg" alt="20071018173736317_1_original.jpg" /></a><br/>Here's the schematic:<br/><br/><a href="http://camelpunch.files.wordpress.com/2007/12/20071018173736317_2.gif" title="20071018173736317_2.gif"><img src="http://camelpunch.files.wordpress.com/2007/12/20071018173736317_2.thumbnail.gif" alt="20071018173736317_2.gif" /></a><br/><br/>Here's the finished product (the second one... after I knew what I was doing. My layout still sucks, but it all fits and is fairly orderly.)<br/><br/><a href="http://camelpunch.files.wordpress.com/2007/12/20071018173736317_3.jpg" title="20071018173736317_3.jpg"><img src="http://camelpunch.files.wordpress.com/2007/12/20071018173736317_3.thumbnail.jpg" alt="20071018173736317_3.jpg" /></a>Stevehttp://www.blogger.com/profile/14070951525184172272noreply@blogger.com0tag:blogger.com,1999:blog-2410889582352367061.post-7946430705802612712007-12-04T11:46:00.000-08:002010-02-21T14:51:06.809-08:00Microchip PIC?At home lately I’ve been trying to learn about electronics and simple analog circuits towards understanding microcontrollers from the bottom up rather than from the top down. In the past, I’ve relied on the kindness of others and/or good books or websites to handle all the component work and stuck to microcontroller programming in C. In C, microcontroller programming is just a bunch of bit operations, shifting, loops, polling, etc. But every time things failed to work like you think they would in “normal” programming (microprocessors) it invariably came down to the hardware, or the interface between the micro controller and the hardware---not the C language implementation or the code itself.<br/><br/>So in working from the electrons up, I’m finally to the point where I’m programming again now that I have a working knowledge of how resistors, capacitors, diodes, transistors, inductors and voltage regulators come into play. But the programming is in assembly, and my only previous assembly experience is on PowerPC architecture (some experience) and 680x0 architecture (a fair amount of experience a long long time ago.)<br/><br/>There are basically two ubiquitous chip families in simple 8 bit microcontroller programming. There are a lot more, but these two are far and away the most popular and often-used. They’re the PIC processors from Microchip and the AVR family from Atmel. The PIC’s seem the most popular overseas and the AVR’s seem most popular in the United states, though the AVR’s are (rightfully) starting to overtake PIC’s.<br/><br/>PIC is an abomination.<br/><br/>Here is a list of things I’ve come to loathe:<br/><br/>1. Program space is organized into 14-bit (yes, that’s FOURTEEN BIT) words.<br/>2. There’s only one register, called W, and it only supports a tiny set of addressing modes.<br/>3. Accessing data is done via the “file registers” which is just a fancy way of describing more 14-bit words in program space.<br/>4. There are no conditional branches, you test condition codes as bit operations with the condition code register and there are only “skip the next instruction” kinds of branching.<br/><br/>I have to stop here and offer an example of how fucked up this is. You have to test the OPPOSITE case you want, with a operand that conditionally SKIPS the next instruction.<br/><br/>;<br/>; I want to see if bit 4 is set in my file register<br/>;<br/>BTFSC SomeFileRegister, 4 ; so I test to see if the bit ISN’T set “Bit Test File and Skip if Clear”<br/>GOTO _TheBitWasSetLabel<br/>.<br/>.<br/>_TheBitWasntSetLabel:<br/>; continue normal execution<br/>.<br/>.<br/><br/>[ elsewhere in the code ]<br/><br/>_TheBitWasSetLabel:<br/>; the condition was met<br/>.<br/>.<br/><br/>Two instructions to do a conditional branch, and you have to test the INVERSE CASE.<br/><br/>Jesus.<br/><br/>What the hell were they thinking?<br/><br/>5. The same thing applies for loop counters, where you do the test at the decrement or increment instruction and SKIP the next statement (which is always a GOTO for conditional branches).<br/>6. It’s an 8-bit architecture, so the working values are all 8 bit, but stored in 14 bit file registers (program memory.) That’s 6 bits wasted when storing data.<br/>7. Storing a string in program space requires building a table of return-literal-value instructions, and then jumping the program counter to the appropriate line by adding to the PC file register. WTF??<br/>8. There’s no stack register. You get 8 nested CALL instructions or INTERRUPTS and you’re out of space.<br/><br/>AVR, fortunately, is a much more sane set of machine instructions, and the C compilers available for the PIC chips handle all this madness for you. Soon I’ll be comfortable enough with the architecture to let the C compiler take care of it for me. Until then I have to boggle at the decision decisions!<br/><br/><a href="http://camelpunch.files.wordpress.com/2007/12/20070927112615868_1.gif" title="20070927112615868_1.gif"><img src="http://camelpunch.files.wordpress.com/2007/12/20070927112615868_1.gif" alt="20070927112615868_1.gif" /></a>Stevehttp://www.blogger.com/profile/14070951525184172272noreply@blogger.com0tag:blogger.com,1999:blog-2410889582352367061.post-47485986044454892007-12-04T11:45:00.000-08:002010-02-21T14:51:06.800-08:00Back to the drawing board...<img src="http://camelpunch.wordpress.comhttp://camelpunch.wordpress.com///C:/dev/camelpunch/www.camelpunch.com/site/images/articles/20070917101640778_1.gif" height="429" width="800" /><br/><br/>After some critiquing by a few N&V forum members more knowledgeable about power supplies than myself (which is likely to be all of them) I've decided I need to do some redesign on the PSU.<br/><br/>I reworked the design a little to reflect my current implementation (the direct battery line for the DTV's screen) and after some charging and testing I've determined:<br/><br/>1) the 3.3v regulator needs to run off the battery directly, not one of the 7805's... it generates a load for the 7805 which heats it up something fierce.<br/>2) my current NiCd cells are probably shot. They don't hold a charge for very long at all.<br/>3) my R1 resistor is too large, as I calculated the charge current incorrectly.<br/>4) I would get a lot more efficiency using a switching battery charger controller like some of the ones offered by Linear.<br/><br/><a href="http://camelpunch.files.wordpress.com/2007/12/20070917101640778_1.gif" title="20070917101640778_1.gif"><img src="http://camelpunch.files.wordpress.com/2007/12/20070917101640778_1.thumbnail.gif" alt="20070917101640778_1.gif" /></a> <img src="http://camelpunch.wordpress.comhttp://camelpunch.wordpress.com///C:/dev/camelpunch/www.camelpunch.com/site/images/articles/20070917101640778_1.gif" height="429" width="800" />Stevehttp://www.blogger.com/profile/14070951525184172272noreply@blogger.com0tag:blogger.com,1999:blog-2410889582352367061.post-54841123752207054742007-12-04T11:41:00.000-08:002010-02-21T14:51:06.792-08:00DTV PSUI worked out a power supply for my DTV system. I'm still working on getting it online as a portable. Right now I've got a good screen for it, and the whole schebang housed in a butt-ugly RadioShack enclosure with all the ports exposed out the side. PS/2, IEC (DIN-6) and Joystick (DB-9) are all mounted.<br/><br/>The DTV portable is going to need a 7.0v to 9.0v line for the screen, a 5v line for the PS/2 keyboard, and a 3.3v line for the DTV itself. Using some scavenged parts, some free samples from National, and a little elbow grease, I worked up a schematic:<br/><br/><a href="http://camelpunch.files.wordpress.com/2007/12/20070911212844634_2.gif" title="20070911212844634_2.gif"><img src="http://camelpunch.files.wordpress.com/2007/12/20070911212844634_2.thumbnail.gif" alt="20070911212844634_2.gif" /></a><br/><br/>The battery I'm using is seven 1.2v NiCd cells I scavenged from next door when Spatialight moved its R&D operation to Korea and let the whole building come in and pick over their trash. I made out like a bandit, scoring a ton of great parts and connectors and stuff.<br/><br/>Anyways, after burning my fingers for a few hours, I finally ended up with:<br/><br/><img src="http://camelpunch.wordpress.com///C:/dev/camelpunch/www.camelpunch.com/site/images/articles/20070911212844634_1.jpg" height="692" width="800" /><a href="http://camelpunch.files.wordpress.com/2007/12/20070911212844634_1.jpg" title="20070911212844634_1.jpg"><img src="http://camelpunch.files.wordpress.com/2007/12/20070911212844634_1.thumbnail.jpg" alt="20070911212844634_1.jpg" /></a><br/><br/>The outputs are on the right. The top is black, that's ground. Below it is green, that's 3.3v. Below that is red, that's 5.0v, and the purple line is unregulated 8.0v-ish straight off the battery. The LCD screen I'm using has its own voltage regulators, so I'm going to feed the battery directly to the screen for now. ·Stevehttp://www.blogger.com/profile/14070951525184172272noreply@blogger.com0tag:blogger.com,1999:blog-2410889582352367061.post-10199215291043929392007-12-04T11:35:00.000-08:002010-02-21T14:51:06.784-08:00OneStation NOACThe "OneStation" is a Made-in-China handheld that contains a NOAC (Nintendo On A Chip, or NES On A Chip) that you can buy mailorder (<a href="http://camelpunch.wordpress.com/wp-admin/if%28confirm%28%27http://www.DealExtreme.com%5Cn%5CnThis%20file%20was%20not%20retrieved%20because%20it%20was%20filtered%20out%20by%20your%20project%20settings.%5Cn%5CnWould%20you%20like%20to%20open%20it%20from%20the%20server?%27%29%29window.location=%27http://www.DealExtreme.com%27">www.DealExtreme.com</a>) for like $30.<br/><br/><img src="http://camelpunch.wordpress.com///C:/dev/camelpunch/www.camelpunch.com/site/images/articles/20070829112336620_1.jpg" height="600" width="800" /><br/><br/>It's styled after the GameBoy Micro, and actually has NOAC and what would normally be considered the "motherboard" of the chip on the cartridge instead of in the main unit. The main unit is simply an audio circuit, a b/w composite video out circuit, the game pad buttons, and the LCD connector for the main OLED display.<br/><br/><img src="http://camelpunch.wordpress.com///C:/dev/camelpunch/www.camelpunch.com/site/images/articles/20070829112336620_2.jpg" height="279" width="800" /><a href="http://camelpunch.files.wordpress.com/2007/12/20070829112336620_1.jpg" title="20070829112336620_1.jpg"><img src="http://camelpunch.files.wordpress.com/2007/12/20070829112336620_1.thumbnail.jpg" alt="20070829112336620_1.jpg" /></a><br/><br/>Since all of the "brains" of this thing are essentially inside the cart, it makes the cart an incredibly compact NES-on-a-chip.<br/><br/><a href="http://camelpunch.files.wordpress.com/2007/12/20070829112336620_2.jpg" title="20070829112336620_2.jpg"><img src="http://camelpunch.files.wordpress.com/2007/12/20070829112336620_2.thumbnail.jpg" alt="20070829112336620_2.jpg" /></a>Stevehttp://www.blogger.com/profile/14070951525184172272noreply@blogger.com0tag:blogger.com,1999:blog-2410889582352367061.post-4056426962623941332007-12-04T11:33:00.001-08:002010-02-21T14:51:06.773-08:00More Scope ResearchI've been looking for a way to look at my circuits without spending large sums of money on a reasonably capable digital sampling oscilloscope.<br/><br/>I want to do analog circuits, mixed signal circuits, and microcontroller work. I want to drive LCD displays and eventually learn how to generate VGA and NTSC signals for displays.<br/><br/>I have big goals, and big dreams, but I'm a husband and a father of young girls and I have a full time day job and I can't afford all this damn electronics equipment.<br/><br/>So I made it my mission to find cheap-ass solutions to expensive test equipment. So far, I'm having only limited success. This post is to try and consolidate the information I've gathered and relate some of my experiences.<br/><br/>Here's what I've got so far:<br/><br/><strong>Parallel Port Oscilloscopes</strong><br/><br/>Scope2k4<br/><br/>http://home.planet.nl/~m.f.hajer/scope2k.htm<br/><br/>I built this, and it works. I don't have real scope probes, but I cannibalized a $10 radio shack multimeter I had retired and mounted everything in that enclosure. This works really well for low speed digital signals. The resolution isn't so great, and the software is pretty simple (I use the free version.)<br/><br/><strong>Sound Card Scopes</strong><br/><br/>Zelscope<br/><br/>http://www.zelscope.com/<br/><br/>with this hardware:<br/><br/>http://xoscope.sourceforge.net/hardware/hardware.html (or bought from http://www.jaycarelectronics.com/productView.asp?ID=KA1811)<br/><br/>Virtins Sound Card Multi-Instrument<br/><br/>http://www.virtins.com/<br/><br/>I built the virtins sound card input protection circuit and I use it with the Zelscope software. The circuit is just some additional impedance on the line and some overload protection:<br/><br/>http://www.virtins.com/Virtins_Sound_Card_MultiInstrument_Manual.pdf<br/><br/><strong>Serial Port Scope</strong><br/><br/>I also discovered, in my surfing around, a serial-port based FPGA-based idea:<br/><br/>http://www.fpga4fun.com/Hands-on_Flashy.html<br/><br/>which shows some promise, though I haven't done any kind of FPGA work in the past and this would be another huge learning experience. The high-speed aspect of it looks promising, but the software seems feature-sparse.<br/><br/><strong>USB Scope</strong><br/><br/>There are many USB scope setups. Many of them way too expensive for me (I'm looking in the under-$200 range) but there are a few standouts.<br/><br/>Hobby Lab USB Scope<br/><br/>http://www.hobbylab.us/USBOscilloscope/Home.htm<br/><br/>Po.Labs Scope<br/><br/>http://po.labs.googlepages.com/<br/><br/>(Same device, different company?)<br/><br/>Hantek DSO-2090<br/><br/>http://www.beigly.com/catalog/product_info.php?products_id=96&osCsid=23bce8203ec673af5b0f959cd5c90642<br/><br/>Thoughts<br/><br/>The sound-card based scopes may be fine for some analog stuff, but I encountered strange behavior that I understand is related to capacitors on the input lines inside the sound card itself (noise reduction?) that make it very hard to use for digital circuits. I can't seem to see a nice square wave, I get drop-off towards 0 volts. I also don't ever see a real voltage level on the sound card scope... it always seems to taper. It's disconcerting, and has put me off of that solution.<br/><br/>The Parallel-port based Scope2k4 seems to work pretty well for digital circuits, but the sampling frequency is pretty low and low resolution (8 bit ADC, max of like 4kHz sampling rate?) Which makes me think it's impractical for any real microcontroller work.Stevehttp://www.blogger.com/profile/14070951525184172272noreply@blogger.com0tag:blogger.com,1999:blog-2410889582352367061.post-64853359458556583752007-12-04T11:33:00.000-08:002010-02-21T14:51:06.762-08:00Scope me, Scope meI wish I had an oscilloscope. I wish it BAD. Why? Because just having a good multimeter really isn't enough to understand what's happening inside the circuits I'm building. Not even close.<br/><br/>It's not enough to know voltage between two points on the circuit, though that IS useful sometimes. And it's difficulty to measure current without disconnecting and reconnecting things. Those are both tools I have with my multimeter from college and I do use them.<br/><br/>But to actually see, say, what's happening to voltage along a line when you have a 1k ohm resistor charging a 220uF cap, versus a 10k ohm resistor charging a 220uF cap, you really need continuous voltage monitoring over time. The multimeter can tell me roughly what the average is, and I can see if it's fluctuating at all, but with a scope you can see actually what's occurring over time, and that's hella useful.<br/><br/>So I built a couple simple PC-based scopes. I wanted more detail, and I didn't want to spend the hundreds of dollars that it takes to get even a half-decent entry level standalone oscilloscope. I think I can probably find a decent 20 year old Tektronix one for like $350 on craigslist or eBay, but it's not even a storage scope, which is something I'd want to have for digital circuit work. Good new ones are in the multiple thousands of dollars, it's all very discouraging.<br/><br/>But a little searching the web turned up a couple of somewhat viable options. They don't sample at NEARLY the frequency you'd need for "serious" scope stuff (like video) though.<br/><br/>A soundcard based scope:<br/><br/><a href="http://camelpunch.wordpress.com/wp-admin/if%28confirm%28%27http://www.virtins.com/%5Cn%5CnThis%20file%20was%20not%20retrieved%20because%20it%20was%20filtered%20out%20by%20your%20project%20settings.%5Cn%5CnWould%20you%20like%20to%20open%20it%20from%20the%20server?%27%29%29window.location=%27http://www.virtins.com/%27">http://www.virtins.com/</a><br/><br/>A parallel port scope:<br/><br/><a href="http://camelpunch.wordpress.com/wp-admin/if%28confirm%28%27http://home.planet.nl/%7Em.f.hajer/scope2k4.html%5Cn%5CnThis%20file%20was%20not%20retrieved%20because%20it%20was%20filtered%20out%20by%20your%20project%20settings.%5Cn%5CnWould%20you%20like%20to%20open%20it%20from%20the%20server?%27%29%29window.location=%27http://home.planet.nl/%7Em.f.hajer/scope2k4.html%27">http://home.planet.nl/~m.f.hajer/scope2k4.html</a><br/><br/>Both of which cost actual money money for the software (which, I'm finding, is really important) but the barrier of entry is low. With the soundcard scope, it's just a couple of resistors and some diodes to make a small circuit to protect the LINE-IN input on the sound card from over-voltage. With the parallel port scope, a couple of cheap ($2?) 8 bit AD converter chips were necessary, but the circuit itself was just a voltage regulator, some resistors and those chips.<br/><br/>I built both of them. Why? Because the soundcard based scope has a fatal flaw. While it's great for analog stuff, there are some capacitors on the line-in on the sound card and they normalize the voltage. If you hook the probes up to a AAA battery, you'll see the 1.5v trace, but then it immediately tapers down to zero. This makes it unusable for any kind of digital work since 1's don't stay 1's for long (at least visually.)<br/><br/>So I built the parallel scope for digital work. It behaves exactly as you'd expect an oscilloscope to behave when you hook up a 1.5v AAA battery to the test leads---you see the 1.5v trace. I hope that this is useful for digital work, even though the scope's maximum sample frequency is 4kHz compared to 44kHz for the soundcard scope and 20Mhz for a very bottom run entry level professional scope. I guess time will tell.<br/>·Stevehttp://www.blogger.com/profile/14070951525184172272noreply@blogger.com0tag:blogger.com,1999:blog-2410889582352367061.post-36342196844676456702007-12-04T11:31:00.000-08:002010-02-21T14:51:06.751-08:00Lucky's Buzzy BallMy dog is almost totally blind now, and while doing laps in the pool is his favorite thing in life (and best, most reliable form of full body exercise) I miss the throw-and-catch from when he was a puppy. And I'm sure he does too---ball-obsessed as he is. He carries a ball with him wherever he goes.<br/><br/>So my solution is to make a beepy-ball. I've started investigating hobby electronics as a way of learning some things that I never really understood and getting enough knowledge to make a few little projects that I've "always wanted to do."<br/><br/>Here's the schematic of version 0.1:<br/><br/><img src="http://camelpunch.wordpress.com///C:/dev/camelpunch/www.camelpunch.com/site/images/articles/20070809121254587_1.gif" height="583" width="800" /><a href="http://camelpunch.files.wordpress.com/2007/12/20070809121254587_1.gif" title="20070809121254587_1.gif"><img src="http://camelpunch.files.wordpress.com/2007/12/20070809121254587_1.thumbnail.gif" alt="20070809121254587_1.gif" /></a><br/><br/>Here's the sample board layout:<br/><br/><img src="http://camelpunch.wordpress.com///C:/dev/camelpunch/www.camelpunch.com/site/images/articles/20070809121254587_2.gif" height="510" width="800" /><a href="http://camelpunch.files.wordpress.com/2007/12/20070809121254587_2.gif" title="20070809121254587_2.gif"><img src="http://camelpunch.files.wordpress.com/2007/12/20070809121254587_2.thumbnail.gif" alt="20070809121254587_2.gif" /></a><br/><br/>These are works in progress, and hopefully will be reduced. ·Stevehttp://www.blogger.com/profile/14070951525184172272noreply@blogger.com0