tag:blogger.com,1999:blog-86819507525567855542024-03-13T23:32:03.749-07:00Nunchuck USB HID MouseHow to build a USB HID mouse using a Nintendo Wii Nunchuck and a PIC18F2550fsilvahttp://www.blogger.com/profile/01103709809548872940noreply@blogger.comBlogger5125tag:blogger.com,1999:blog-8681950752556785554.post-15224648567314402182008-06-03T23:00:00.000-07:002008-06-03T06:23:53.668-07:00Introduction<span lang="EN-US">For the past months I have been teaching myself microcontrollers, just for kicks, and my first real project was hooking up two accelerometers<</span><span lang="EN-US">->microcontroller<->PC through USB and see wh</span><span lang="EN-US">at kind of games I could do with that. I completed </span><span lang="EN-US">the hardware, but had little time to do any fun games. Probably in the summer.</span> <p class="MsoBodyText"><span lang="EN-US">In related news, my mother is a teacher at a local school and one of her students cannot use the mouse, he has a motor problem that I do not know the name – when he tries to hold something steadily, his hands start shaking and he loses all precision in his movements. Well, my mother had seen my 'accelerometers' working, so she asked me if I could do a special mouse for the kid that didn't require steady control. Well, I've read that there are more appropriate methods for cases like this, such as eye control, but they are expensive and you cannot carry it around from computer to computer. Plus, since my mother was paying the bill, it seemed like a good idea to do something like this from an educational point of view :D .</span></p> <p class="MsoBodyText"><span lang="EN-US">After I did the setup I described in the first paragraph, I had been r</span><span lang="EN-US">eading about some nifty experiments with the nunchuck controller. For 20€ you get an accelerometer, 2 buttons and a joystick – a lot of bang-for-the-buck. Plus it would give a pretty sexy mouse. So when I started thinking about the project, it was quite an easy choice of nunchuck vs discrete accelerometers (<a href="http://cgi.ebay.co.uk/KXPS5-3g-3-Axis-Accelerometer-Development-Board-PIC-AVR_W0QQitemZ120268831706QQihZ002QQcategoryZ36323QQssPageNameZWDVWQQrdZ1QQcmdZViewItem">this</a> and <a href="http://cgi.ebay.co.uk/3-Axis-low-g-Accelerometer-MMA7260-prototype-PCB_W0QQitemZ350066055160QQihZ022QQcategoryZ36323QQssPageNameZWDVWQQrdZ1QQcmdZViewItem">this</a> for example, if you know any cheap dealers in europe, please tell me).<span style=""> </span>Plus I had found some nice information on the internet, and it seemed it wouldn't be that hard to wire up.</span></p> <p class="MsoBodyText"><span lang="EN-US">In the next pages I am going to report what I did and how I did, just so that anyone which is seeking information as I did can use it as reference. I will talk about:</span></p> <ul><li><!--[if !supportLists]--><!--[endif]--><span lang="EN-US">Where did I learn what I needed to know</span></li></ul> <ul><li><!--[if !supportLists]--><!--[endif]--><span lang="EN-US">How I<span style=""> </span>wired the hardware</span></li></ul> <ul><li><!--[if !supportLists]--><span style=";font-family:Wingdings;font-size:9;" lang="EN-US" ><span style=""><span style=""> </span></span></span><!--[endif]--><span lang="EN-US">How I made it a HID mouse that works in any computer (used example code from Microchip's PICDEM USB demo board :D)</span></li></ul> <ul><li><!--[if !supportLists]--><span lang="EN-US">How am I processing the joystick and acceleration data to generate mouse movement</span></li></ul> <ul><li><!--[if !supportLists]--><span style=";font-family:Wingdings;font-size:9;" lang="EN-US" ><span style=""><span style=""> </span></span></span><!--[endif]--><span lang="EN-US">Discuss that accelerometers working as inclinometers really suck compared to normal mice.</span></li></ul> <p class="MsoBodyText"><span lang="EN-US">I would like to meet the kid and make a video of him using the mouse, </span><span lang="EN-US">but I'm currently busy (exams) and don't have much time. If anyone has knowledge/experience about what works better in a situation like his, I would be very very interested to know, please post a comment and I will be extremely grateful.</span><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_H5-g4pyzTOY/SEUVDeyYbDI/AAAAAAAAAA8/hRj_hj9t2jc/s1600-h/nun1.jpeg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp0.blogger.com/_H5-g4pyzTOY/SEUVDeyYbDI/AAAAAAAAAA8/hRj_hj9t2jc/s320/nun1.jpeg" alt="" id="BLOGGER_PHOTO_ID_5207591693672016946" border="0" /></a></p><p style="text-align: center;" class="MsoBodyText"><span lang="EN-US"><span style="font-style: italic;font-size:85%;" >The Nunchuck Mouse with its guts open.<br /></span></span></p><p style="text-align: left;" class="MsoBodyText"><span lang="EN-US"><span style="font-size:100%;">I am currently building this blog so there are quite a few pages missing. I will </span></span><span lang="EN-US"><span style="font-size:100%;">probably </span></span><span lang="EN-US"><span style="font-size:100%;">complete it till Sunday.</span><br /></span></p>fsilvahttp://www.blogger.com/profile/01103709809548872940noreply@blogger.com1tag:blogger.com,1999:blog-8681950752556785554.post-59127558328145762302008-06-03T22:00:00.000-07:002008-06-03T06:25:13.985-07:00References<style type="text/css">!-- @page { size: 8.5in 11in; margin: 0.79in } P { margin-bottom: 0.08in } --> </style> <p>This setup is composed of two parts: the nunchuck <-> microcontroller interface, and the computer <-> PC interface. I will list some references I used in the course of this project.</p><p> <style type="text/css"> <!-- @page { size: 8.5in 11in; margin: 0.79in } P { margin-bottom: 0.08in } H3 { margin-bottom: 0.08in } H3.western { font-family: "Arial", sans-serif } H3.cjk { font-family: "DejaVu Sans" } H3.ctl { font-family: "DejaVu Sans" } --> </style> </p><h3 class="western"><span style="font-size:100%;">Nuchuck I2C interface</span></h3> <p>[1] <a href="http://www.windmeadow.com/node/42?page=1">http://www.windmeadow.com/node/42?page=1</a> </p> <p>In this site Chad explains how to hook up the Nunchuck to an Arduino board. He also discusses the protocol and wiring.</p> <p>[2] <a href="http://www.ccsinfo.com/forum/viewtopic.php?t=32753&start=11">http://www.ccsinfo.com/forum/viewtopic.php?t=32753&start=11</a></p> <p>Forum post about how to use the nunchuck with a PIC using the I2C libraries of the CCS compiler. Interesting to understand the I2C protocol and write/read addresses. One poster reveals that you can use 3.3V inputs for I2C in certain microcontroller ports. </p> <p>[3] <a href="http://www.wiili.org/index.php/Wiimote/Extension_Controllers/Nunchuk#Ways_of_retrieving_the_Nunchuk_data">http://www.wiili.org/index.php/Wiimote/Extension_Controllers/Nunchuk</a></p> <p>Discussion of the Nunchuck characteristics, including wiring and data interpretation.</p> <p>[4] <a href="http://www.electro-tech-online.com/robotics-chat/36190-communicating-srf05-using-pic18f452.html">http://www.electro-tech-online.com/robotics-chat/36190-communicating-srf05-using-pic18f452.html</a></p> <p>The I2C functions from Microchip's C18 Library weren't working very well, but Pommie's (second post) functions worked perfectly. </p> <p>Other sites:</p> <p><a href="http://todbot.com/blog/bionicarduino/">http://todbot.com/blog/bionicarduino/</a></p> <p>Interesting series of lectures to learn some things about microcontrollers(Arduino) in general and a bit about using the Nunchuck.</p><br /><h3 class="western"><span style="font-size:100%;">PIC18F2550 USB Interface</span></h3> <p>[5] <a href="http://ww1.microchip.com/downloads/en/devicedoc/39632c.pdf">http://ww1.microchip.com/downloads/en/devicedoc/39632c.pdf</a></p> <p>The datasheet.</p> <p>[6] <a href="http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2124&param=en532204&page=wwwFullSpeedUSB">http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2124&param=en532204&page=wwwFullSpeedUSB</a></p> <p style="margin-bottom: 0in;">The <span style="">'</span><span style="color: rgb(0, 0, 0);"><span style="font-family:Times New Roman,serif;"><span style="font-size:100%;"><span style="">MCHPFSUSB v1.3 USB Framework'</span></span></span></span><span style="color: rgb(153, 153, 153);"><span style="font-family:Verdana;"><span style="font-size:130%;"><b> </b></span></span></span>provides example code for the HID mouse. It also includes bootloader software/firmware, which is nice. </p> <p style="margin-bottom: 0in;">Some months ago there was a wiki called 'pic18fusb' that had lots of interesting information. It seems to be gone, but I've found some sites with some of that info: <a href="http://www.piccoder.co.uk/content/view/42/26/"><br /></a></p><p style="margin-bottom: 0in;"><a href="http://www.piccoder.co.uk/content/view/42/26/">http://www.piccoder.co.uk/content/view/42/26/</a></p> <p style="margin-bottom: 0in;"><a href="http://forum.microchip.com/printable.aspx?m=162505">http://forum.microchip.com/printable.aspx?m=162505</a></p> <p style="margin-bottom: 0in;"><a href="http://www.theroboticshomepage.com/joomla1/content/view/17/30/">http://www.theroboticshomepage.com/joomla1/content/view/17/30/</a></p> <p style="margin-bottom: 0in;"><br /></p> <p></p>fsilvahttp://www.blogger.com/profile/01103709809548872940noreply@blogger.com0tag:blogger.com,1999:blog-8681950752556785554.post-50267801362582518012008-06-03T09:00:00.000-07:002008-06-08T08:36:33.817-07:00Hardware<span style="font-size:100%;"><span style="color: rgb(0, 0, 0);font-family:verdana;" >The circuit is composed of several parts. It is not very complex, as you can see from the following block diagram:</span><a style="color: rgb(0, 0, 0);" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_H5-g4pyzTOY/SEv07DXvWDI/AAAAAAAAABc/KyXIGk0oYVs/s1600-h/schematic.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp0.blogger.com/_H5-g4pyzTOY/SEv07DXvWDI/AAAAAAAAABc/KyXIGk0oYVs/s400/schematic.png" alt="" id="BLOGGER_PHOTO_ID_5209526689338447922" border="0" /></a></span><p style="color: rgb(0, 0, 0);"> </p><p style="color: rgb(0, 0, 0);font-family:verdana;"><span style="font-size:100%;">The nunchuck communicates by I2C with the microcontroller, which in turn processes the data and sends 'mouse data' to the computer by USB. There is one detail, though. The nunchuck works at 3.3V, while USB gives 5V. Some have reported that the nunchuck works correctly when wired with 5V [1], and I've tried and it works, but it will probably reduce the nunchuck's lifespan. So I've inserted a voltage converter between the nunchuck and the microcontroller. The more elegant solution would be to use the microcontroller at 3.3V, but when I built the circuit I did not know if one could do the USB communication at that voltage. The PIC18F2550 datasheet discusses such possibilities around page 165. </span></p> <p style="color: rgb(0, 0, 0);font-family:verdana;"><span style="font-size:100%;"> The whole circuit is represented in the following schematic:</span></p> <span style="font-size:100%;"><a style="color: rgb(0, 0, 0);" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_H5-g4pyzTOY/SEv0j1C61cI/AAAAAAAAABU/pDBH4wmd4dU/s1600-h/circuit.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp2.blogger.com/_H5-g4pyzTOY/SEv0j1C61cI/AAAAAAAAABU/pDBH4wmd4dU/s400/circuit.png" alt="" id="BLOGGER_PHOTO_ID_5209526290356032962" border="0" /></a></span> <p style="margin-bottom: 0cm; color: rgb(0, 0, 0);font-family:verdana;"><span style="font-size:100%;">I will briefly describe each 'subsystem'. </span></p> <ul style="color: rgb(0, 0, 0);"><li><p style="margin-bottom: 0cm;"><span style="font-size:100%;"><span style="font-family:verdana;">Oscillator</span><br /><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp3.blogger.com/_H5-g4pyzTOY/SEv07at9xFI/AAAAAAAAABk/cYKjWZqjMMI/s400/circuitOSC.png" alt="" id="BLOGGER_PHOTO_ID_5209526695605683282" border="0" /><span style="font-family:verdana;">A 20MHz crystal is used as the oscillator, just as in the PICDEM USB demo board. Since we will be using code written for that circuit, we should try to be as compatible as possible. Still, to use other crystal you just need to set the appropriate configuration bits. </span></span></p></li></ul> <ul style="color: rgb(0, 0, 0);font-family:verdana;"><li><span style=";font-family:verdana;font-size:100%;" >ICSP<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_H5-g4pyzTOY/SEv07lfmI1I/AAAAAAAAABs/S32RpFigV-s/s1600-h/circuitICSP.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp1.blogger.com/_H5-g4pyzTOY/SEv07lfmI1I/AAAAAAAAABs/S32RpFigV-s/s400/circuitICSP.png" alt="" id="BLOGGER_PHOTO_ID_5209526698498204498" border="0" /></a></span><span style="font-size:100%;"><span style="font-family:verdana;">In-Circuit Serial Programming is a useful method to program the microcontroller. You just plug in the programmer in the ICSP header and you can reprogram the chip as needed. In my case I used a PicKit2, but any other programmer that supports ICSP should work. The 1KOhm resistor is used to provide insulation from the rest of the circuit, as recommended in the PicKit2 u</span>ser guide. If you plan on programming your microcontroller by USB bootloading, the inclusion of a permanent ICSP header is unnecessary. You just have to program the chip using ICSP once (in another circuit, for example) and use the USB bootloader to reprogram it when needed.</span></li><li><span style="font-size:100%;">USB<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_H5-g4pyzTOY/SEv076RAwLI/AAAAAAAAAB0/WCAd3MHKtYo/s1600-h/circuitUSB.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp0.blogger.com/_H5-g4pyzTOY/SEv076RAwLI/AAAAAAAAAB0/WCAd3MHKtYo/s400/circuitUSB.png" alt="" id="BLOGGER_PHOTO_ID_5209526704074178738" border="0" /></a></span><span style=";font-family:verdana;font-size:100%;" >The USB connection is quite simple. The +5V power is drawn from the USB port. I happened to switch the USB + & - so it wasn't working, but if the computer doesn't communicate (start enumeration) with the microcontroller, they are probably switched or the microcontroller is not working well (bad programming?). If the computer tells you that the device failed enumeration, they are well connected but you probably have electromagnetic interference between the wires. When I first built the circuit on a breadboard that was fairly common, in a stripboard it still happened some times, mostly because I was using a small board inserted in a USB extension cord connected to my circuit with long wires. Ugh. It works properly with a savaged USB cord from a el-cheapo USB hub. I could also have cut the extension cord in half, but I'll delay that until the next project. The 220 nF capacitor is needed for the internal 3.3V regulator in the microcontroller, used to drive the USB transciever. The datasheet indicates that the regulator's power is not enough to drive anything other that the transciever and pullups, so we can't use it in the nunchuck. The datasheet advises 220 nF, but I think I am using a 100 nF capacitor and it works.</span></li><li><span style="font-size:100%;">Bootloading <a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_H5-g4pyzTOY/SEv2XrFO1WI/AAAAAAAAAB8/S9PLLFLl2M4/s1600-h/circuitBOOTLOAD.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp1.blogger.com/_H5-g4pyzTOY/SEv2XrFO1WI/AAAAAAAAAB8/S9PLLFLl2M4/s400/circuitBOOTLOAD.png" alt="" id="BLOGGER_PHOTO_ID_5209528280546202978" border="0" /></a></span><span style="font-size:100%;"><span style="font-size:100%;">Using the appropriate firmware found in the </span><span style=""><span style="font-size:100%;">'</span><span style="color: rgb(0, 0, 0);"><span style="font-size:100%;">MCHPFSUSB v1.3 USB</span> Framework' we can do USB bootloading. USB bootloading consists in programming the microcontroller directly by the USB connectio<span style="font-size:100%;">n. You still need to program the chip once with ICSP, to load the 'Host' program that is capable</span> of rewriting the code of the 'main' program in the microcontroller. To use the utility provided in the USB Framework by microchip, you need two pushbuttons: on in the reset pin, and the other in the RB4 pin. They work as pullups that short to ground when the button is down. If you reset the microcontroller normally, the bootloaded jumps to the main program and it all works normally. If you reset the microcontroller while holding down the S2 pushbutton, the bootloader will not jump to the main program but will instead start the microcontroller in 'programming' mode, and you will be able to program it from the computer.</span></span></span></li><li><span style="font-size:100%;"> Voltage Regulator <a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_H5-g4pyzTOY/SEv2srAONlI/AAAAAAAAACM/hA3eKYQxlRE/s1600-h/circuitOut.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp1.blogger.com/_H5-g4pyzTOY/SEv2srAONlI/AAAAAAAAACM/hA3eKYQxlRE/s400/circuitOut.png" alt="" id="BLOGGER_PHOTO_ID_5209528641302443602" border="0" /></a>A</span><span style="font-size:100%;">s said, the nunchuck's circuits are designed for 3.3V, but, for example, the LIS3L accelerometer datasheet specifies the absolute maximum voltage as 6V and it works with 5V power, but it shouldn't be very good for the nunchuck's health. So I used a 3.3V regulator between the nunchuck and the microcontroller. I wanted to use a 3.3V Regulator, but my local store did not have those, so I used and adjustable voltage regulator LM117 with the appropriate resistors. </span></li><li><span style="font-size:100%;">Potentiometer <a style="font-weight: bold;" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_H5-g4pyzTOY/SEv2X-KcA8I/AAAAAAAAACE/0iX_oXLAIFo/s1600-h/circuitPotenciometro.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp0.blogger.com/_H5-g4pyzTOY/SEv2X-KcA8I/AAAAAAAAACE/0iX_oXLAIFo/s400/circuitPotenciometro.png" alt="" id="BLOGGER_PHOTO_ID_5209528285668312002" border="0" /></a></span><a style="font-weight: bold;" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_H5-g4pyzTOY/SEv2X-KcA8I/AAAAAAAAACE/0iX_oXLAIFo/s1600-h/circuitPotenciometro.png"></a>We want to change the mouse speed as needed. The easiest method to do it (that I know of) would be to read an analog voltage between 5V-0V in the AN8 port, controlled by a potentiometer. That's it. </li><li><span style="font-size:100%;">Connecting to the Nunchuck - Using the resulting 4 wires – 3.3V, Clock, Data, GND - we only need to connect them to the nunchuck. In most of the sites I've read in the internet people have cut the cord, except for <a href="http://todbot.com/blog/2008/02/18/wiichuck-wii-nunchuck-adapter-available/">this</a> one that created some nice connectors. I started by connecting wires directly to the nunchuck port and it worked well. In the final circuit, due to space constraints, I decided to cut the cord, but any of the two methods work. For the connector 'pinout', check <a href="http://todbot.com/blog/2008/02/18/wiichuck-wii-nunchuck-adapter-available/">this site</a> and if you cut the cord check <a href="http://www.windmeadow.com/node/42?page=1">this one</a>. </span></li></ul> <p style="margin-bottom: 0cm; color: rgb(0, 0, 0);"><span style="font-size:130%;">Cost</span></p><p style="margin-bottom: 0cm; color: rgb(0, 0, 0);"> </p><table style="width: 651px; height: 356px; text-align: left; margin-left: auto; margin-right: auto; color: rgb(0, 0, 0);" border="1" cellpadding="4" cellspacing="0"> <col width="679"> <col width="679"> <tbody><tr valign="top"> <td width="679"> <p><span style="font-size:100%;">Parts</span></p> </td> <td width="679"> <p><span style="font-size:100%;">Cost</span></p> </td> </tr> <tr valign="top"> <td width="679"> <p><span style="font-size:100%;">PIC18F2550</span></p> </td> <td width="679"> <p><span style="font-size:100%;">8 € </span></p> </td> </tr> <tr valign="top"> <td width="679"> <p><span style="font-size:100%;">USB Cable</span></p> </td> <td width="679"> <p><span style="font-size:100%;">~ 1 € (salvaged)<br /></span></p> </td> </tr> <tr valign="top"> <td width="679"> <p><span style="font-size:100%;">Voltage Regulator</span></p> </td> <td width="679"> <p><span style="font-size:100%;">1 €<br /></span></p> </td> </tr> <tr valign="top"> <td width="679"> <p><span style="font-size:100%;">2x Button</span></p> </td> <td width="679"> <p><span style="font-size:100%;">1 €</span></p> </td> </tr> <tr valign="top"> <td width="679"> <p><span style="font-size:100%;">Resistances, Capacitors, Wires, Stripboard, Headers</span></p> </td> <td width="679"> <p><span style="font-size:100%;">~ 2 €</span></p> </td> </tr> <tr valign="top"> <td width="679"> <p><span style="font-size:100%;">20MHz Cristal</span></p> </td> <td width="679"> <p><span style="font-size:100%;">1 € </span></p> </td> </tr> <tr valign="top"> <td width="679"> <p><span style="font-size:100%;">Plastic Box</span></p> </td> <td width="679"> <p><span style="font-size:100%;">1.5 €</span></p> </td> </tr> <tr valign="top"> <td width="679"> <p><span style="font-size:100%;">Nunchuck</span></p> </td> <td width="679"> <p><span style="font-size:100%;">20€</span></p> </td> </tr> <tr valign="top"> <td width="679"> <p align="left"><span style="font-size:100%;">Potentiometer</span></p> </td> <td width="679"> <p><span style="font-size:100%;">1.5€</span></p> </td> </tr> <tr valign="top"> <td width="679"> <p align="right"><span style="font-size:100%;"><br /></span> </p> </td> <td width="679"> <p><span style="font-size:100%;"><br /></span> </p> </td> </tr> <tr valign="top"> <td width="679"> <p align="right"><span style="font-size:100%;">Total</span></p> </td> <td width="679"> <p><span style="font-size:100%;">37€</span></p> </td> </tr> </tbody></table><div style="text-align: center;"><br /></div><p style="margin-left: 0.64cm; margin-bottom: 0cm; color: rgb(0, 0, 0); text-align: center;"><span style="font-size:100%;">And that's it. Here is how my circuit looks like assembled in a stripboard:</span></p> <ol style="color: rgb(0, 0, 0);"><li><p style="margin-bottom: 0cm;"><span style="font-size:100%;"><span style="color: rgb(0, 0, 0);">The microcontroller, with the ICSP header and buttons removed:</span><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_H5-g4pyzTOY/SEv30vr2xtI/AAAAAAAAACU/QIXm7lZC4EQ/s1600-h/circuito1.jpeg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp1.blogger.com/_H5-g4pyzTOY/SEv30vr2xtI/AAAAAAAAACU/QIXm7lZC4EQ/s400/circuito1.jpeg" alt="" id="BLOGGER_PHOTO_ID_5209529879509780178" border="0" /></a><br /></span></p></li><li><p style="margin-bottom: 0cm;"><span style="font-size:100%;">The Voltage Regulator with connection to the nunchuck: <a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_H5-g4pyzTOY/SEv3001YgSI/AAAAAAAAACc/ZxP1A0s-GuM/s1600-h/circuito2.jpeg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp0.blogger.com/_H5-g4pyzTOY/SEv3001YgSI/AAAAAAAAACc/ZxP1A0s-GuM/s400/circuito2.jpeg" alt="" id="BLOGGER_PHOTO_ID_5209529880891916578" border="0" /></a></span></p> </li></ol><span style="font-size:100%;"><br /></span>fsilvahttp://www.blogger.com/profile/01103709809548872940noreply@blogger.com4tag:blogger.com,1999:blog-8681950752556785554.post-26920109598547313222008-06-03T08:00:00.000-07:002008-06-21T12:14:48.724-07:00Software<p>The software side can be decomposed into 3 'subsystems':</p><p> </p><h3 class="western">1) USB HID mouse code</h3> <p>As said, example code from the PICDEM USB demo board will be used. The project we will use is in the directory 'MCHPFSUSB\fw\Hid\Mouse'. It has various files, implementing the USB and HID protocol. The 'user\user_mouse.c' file is where our project's specific code will be. This project was originally written with a PIC18F4550 in mind, so one must make some minor changes to the code:</p> <ul><li><p>'io_cfg.h' – since the 2550 doesn't have a D port, remove all references to the D port in the LED definitions (or replace with B)</p> </li><li><p>'autofiles/usbcfg.h' – due to differences between our board and the PICDEM USB board, we must comment these 2 lines: #if defined(PIC18F4550_PICDEM_FS_USB) </p> </li></ul> <p style="font-family:courier new;"><span style="font-size:85%;"> #define USE_SELF_POWER_SENSE_IO<br /> #define USE_USB_BUS_SENSE_IO</span></p> <p> to</p><p><span style="font-size:85%;"> //#define USE_SELF_POWER_SENSE_IO<br /> //#define USE_USB_BUS_SENSE_IO</span></p><ul><li><p>'rm18f4550.lkr' – change 'FILES p18f4550.lib' to 'FILES p18f2550.lib'</p> </li><li><p>In MPLAB, Configure->Select Device , change to 18f2550.</p> </li></ul> <p> Programming the PIC18F2550 with this project should create a USB HID mouse that moves the pointer in a circle. If not there is something wrong! To diagnose USB connection problems I've used two programs: <a href="http://sourceforge.net/projects/usbsnoop/">SnoopyPro</a> and <a href="http://www.ftdichip.com/Resources/Utilities.htm">USBVIEW </a>. With USBVIEW you can check if the device failed enumeration or was recognized successfully. With SnoopyPro you can log the traffic between the device and the computer – very nice! </p> <p> Now one is able to send mouse events to the computer, by controlling the buffer array in the Emulate_Mouse() function.</p> <p> </p><h3 class="western">2) Nunchuck I2C Communication Code</h3> <p> For some reason I wasn't being able to get the C18 library I2C functions to work with the nunchuck. Luckily, I've found some routines in a forum (written by pommie[4]) that worked perfectly. The communication with the nunchuck works as follows:</p> <ul><ul><li><p>MCU sends nunchuck address (0x52) + write bit (1) = 0xA5</p> </li><li><p>MCU writes 0 (8 bits)</p> </li><li><p>MCU stops communication</p> </li><li><p>Wait a bit for nunchuck to get data ready</p> </li><li><p>MCU sends nunchuck address (0x52) + read bit (0) = 0xA4</p> </li><li><p> (MCU reads byte + sends ACK ) 5 times</p> </li><li><p>MCU reads byte, sends NACK</p> </li><li><p>MCU stops communication</p></li></ul></ul><p> </p><br />And there you go. 6 bytes of data with button presses, accelerometer status and joystick status. The meaning of each byte is explained in a nice table in <a href="http://www.wiili.org/index.php/Wiimote/Extension_Controllers/Nunchuk#Meaning_of_the_Nunchuk_data">[3]</a>.<br /><br /><h3 class="western">3) Generating mouse events with the Nunchuck Data</h3> <p>The buffer array in 'Emulate_Mouse()' has the following structure: </p> <p>- 1<sup>st</sup> byte: first bit for left click, second bit for right click, remaining bits are padding</p> <p> - 2<sup>nd</sup> and 3<sup>rd</sup> bytes: X and Y desired dislocation of the cursor. </p> <p>The whole work goes in the Emulate_Mouse() function. </p> <h2 style="font-weight: bold; color: rgb(0, 0, 0);font-family:arial;" class="western"><span style="font-size:130%;">Buttons</span></h2> <p>The two buttons on the nunchuck are good candidates for left and right mouse buttons. The C button (bigger) will be the left, and the Z the right. The code to check for button presses is the following:</p> <p style="font-family:courier new;"><span style="font-size:85%;"> nunchuck_getdata(array);<br />buffer[1] = buffer[2] = buffer[0] = 0;</span></p> <p style="font-family:courier new;"><span style="font-size:85%;">//buttons<br />if((array[5] & 0b11) == 0b01)<br />{<br />buffer[0] = 2;<br />dirty = 2; //to keep it sending signal, even 0, to release the buttons<br />}<br />if((array[5] & 0b11) == 0b0)<br />{<br />buffer[0] = 1;<br />dirty = 2;<br />}</span></p> <p>Where array if a 6 byte array and dirty is a decreasing counter that makes the MCU send mouse signals to the computer even when the buttons are not pressed. The problem is that without it, when we released the button the MCU wouldn't send any message to the computer saying that the button was released. The nunchuck 5<sup>th</sup> byte is a bit strange: when the Z button is down, it's first 2 bits are 0x01, when C is down, it's 0x00! Testing for that we can fill the buffer[0] variable with the appropriate values.</p> <h2 style="font-weight: bold; color: rgb(0, 0, 0);" class="western"><span style="font-size:130%;">Potentiometer</span></h2> <p>We have a potentiometer in the circuit to control the mouse movement speed. Reading it is simple: just read the ADC in port AN8. Initialization:</p> <p style="font-family:courier new;"><span style="font-size:85%;"> OpenADC( ADC_FOSC_32 & ADC_RIGHT_JUST & ADC_12_TAD, ADC_CH8 & ADC_REF_VDD_VSS & ADC_INT_OFF, 6 );<br />SetChanADC(ADC_CH8);</span></p> <p>Reading the value:</p> <p style="font-family:courier new;"><span style="font-size:85%;"> ConvertADC(); // Start conversion<br />while( BusyADC() ); // Wait for ADC conversion<br />adc = ReadADC(); // Read 10bits</span></p> <p>Calculating the speed:</p> <p style="font-family:courier new;"><span style="font-size:85%;"> delta = 1+(adc >> 7);<br />if(delta == 8)<br />delta = 14;<br />if(delta == 7)<br />delta = 10;<br />if(delta == 6)<br />delta = 8;</span></p> <p>The ifs are to induce a little nonlinearity, so that we can reach higher velocities than our linear scale allows. </p> <h2 style="font-weight: bold; color: rgb(0, 0, 0);" class="western"><span style="font-size:130%;">Joystick</span></h2> <p> The nunchuck's joystick is easy to control, and while it lacks precision it is not that bad as a mouse. </p> <p style="font-family:georgia;"><span style="font-size:100%;">I used a threshold approach, so that small vibrations of the joystick produce no effect. The code:<br /></span></p><p style="font-family:courier new;"><span style="font-size:85%;">if(array[0] > MAXTH)<br />buffer[1] = delta+delayAdd;<br />if(array[0] <> MAXTH)<br />buffer[2] = -delta-delayAdd;</span></p> <p> delayAdd is a variable that is incremented while there is movement, to create a feeling of acceleration. MAXTH & MINTH are constants chosen by experimentation. (The full code is attached to the post)</p> <h2 style="font-weight: bold; color: rgb(0, 0, 0);font-family:arial;" class="western"><span style="font-size:130%;">Accelerometer</span></h2> <p>I've used a similar threshold approach for the accelerometer values:</p> <p style="font-family:courier new;"><span style="font-size:85%;">if(ax > ThAccX)<br />buffer[1] = delta;<br />if(ax < -ThAccX) buffer[1] = -delta; if(ay > ThAccY)<br />buffer[2] = -delta;<br />if(ay < -ThAccY) buffer[2] = delta;</span></p> <p>Again ThAccX,ThAccY were chosen by experimentation. </p> <h2 style="font-weight: bold; color: rgb(0, 0, 0);" class="western"><span style="font-size:130%;">Sending the Data</span></h2> <p style="font-family:courier new;"><span style="font-size:85%;"> if(buffer[0] != 0 || buffer[1] != 0 || buffer[2] != 0 || dirty > 0)<br />{<br />dirty--;<br />HIDTxReport(buffer,3);<br />}</span></p> <p>If there is data to send or release events, send. Simple. </p><br /><br /><p>So that's it. This post covers the main ideas behind the code inside the mouse. </p> <p>The full MPLAB workspace is <a href="http://rapidshare.com/files/124073935/NunchuckMouse.zip.html">here</a>.</p>fsilvahttp://www.blogger.com/profile/01103709809548872940noreply@blogger.com0tag:blogger.com,1999:blog-8681950752556785554.post-18607635196109326932008-06-03T07:00:00.000-07:002008-06-22T16:27:14.230-07:00ConclusionI've made a youtube video of the mouse:<br /><br /><object width="425" height="350"><param name="movie" value="http://www.youtube.com/v/b-fS0mdxHnA"><embed src="http://www.youtube.com/v/b-fS0mdxHnA" type="application/x-shockwave-flash" width="425" height="350"></embed></object><br />As you can see, normal mouses are much better for normal usage. Maybe another GUI paradigm would fit like a glove to an accelerometer based mouse. Wii's games certainly do :)<br /><br />Theoretically, one could calculate the 2D position of the mouse with the XY acceleration signals, given that they are perpendicular to the gravity axis. The problem is that current MEMS accelerometers, well, suck, i. e., they have significant noise and drift. To calculate position, you need to integrate the signal (twice) , and integrating a very small drift leads to bad results. Plus that mouse wouldn't work in inclined surfaces.<br /><br />With a 3-axis accelerometer + a gyroscope it would be possible to workout a nice 3D motion sensor (IMU, kalman filter). If you know where to get a cheap gyroscope please comment :)<br /><br />My mother told me that the kid didn't get along very well with the mouse. He was very impatient and got annoyed at every mistake. Maybe after some training he can get better at it. I've recently found <a href="http://www.steadymouse.com/">this</a>, and I'm going to suggest it, at least he can use it without special equipment.<br /><br />I hope this information was usefull to anyone. If you have any questions, fell free to ask through the comments or francisco.silva@REMOVETHISalunos.fc.up.ptfsilvahttp://www.blogger.com/profile/01103709809548872940noreply@blogger.com4