tag:blogger.com,1999:blog-82992123461860053512024-03-05T19:59:01.787+01:00jallibTalking about jallib, jalv2, PIC microcontrollers...Sebastien Lelonghttp://www.blogger.com/profile/00317258446230687333noreply@blogger.comBlogger24125tag:blogger.com,1999:blog-8299212346186005351.post-64415727530237275562009-09-07T19:29:00.011+02:002010-01-03T11:00:02.572+01:00Jaluino v1.1: enhanced Arduino-like board<div style="text-align: center;"><span style="color: rgb(102, 0, 0); font-weight: bold;">Jaluino, with user guide, schematics, PCB, shields, etc... can now be reached on the following sites:</span><br /><br /><span style="font-weight: bold;">Main site</span>: <a href="http://jaluino.org/">http://jaluino.org</a><br /><span style="font-weight: bold;">Repository</span>: <a href="http://jaluino.googlecode.com/">http://jaluino.googlecode.com</a><br /><span style="font-weight: bold;">Group</span>: <a href="http://groups.google.com/group/jaluino">http://groups.google.com/group/jaluino</a><br /></div><br /><br /><br /><br /><a href="http://jallib.blogspot.com/2009/08/building-jaluino-v10.html">Last time</a>, I built Jaluino v1.0, the very first version of <span style="font-weight: bold;">Jaluino</span>. Jaluino is an <span style="font-style: italic;">Arduino-like</span> board (some even say a <span style="font-style: italic;">clone</span>), based on a Microchip PIC 18F4550, and powered by <a href="http://www.casadeyork.com/jalv2/">jalv2</a> and <a href="http://code.google.com/p/jallib/">jallib</a>. This first version was very encouraging, but several points had to be improved. Quite <a href="http://groups.google.com/group/jallib/browse_thread/thread/87cd558764cdb52e">a lot of has been discussed</a>, now has come the next version: <span style="font-weight: bold;">Jaluino v1.1</span><br /><br /><br /><span style="font-weight: bold;font-size:130%;" >What's been improved ?<br /></span><br />Several important points were discussed and improved:<br /><br /><ul><li><span style="font-weight: bold;">i²c support</span>. Jaluino v1.0 lacked i²c support, this new Jaluino v1.1 version now provides a <span style="font-weight: bold;">new connector</span>, and two <span style="font-weight: bold;">jumpers</span> to select whether the board should act as a <span style="font-style: italic;">master</span> or a <span style="font-style: italic;">slave</span> (more on this on a later tutorial I guess). This is an important point, as i²c is widely used. Jaluino now provides mostly important communication connectors: <span style="font-style: italic;">serial</span>, <span style="font-style: italic;">USB</span>, <span style="font-style: italic;">ICSP</span> and <span style="font-style: italic;">i²c</span>.</li><li><span style="font-weight: bold;">3.3V power supply</span>. Lots of components uses this voltage. Jaluino v1.1 provides 3.3V through the power supply connector. There are several options to choose the regulator: LM3940, LD1117V33, LM1117T, LM1086, LF33V, ... Not all have the same pinning. For now, we provide two options:</li><ul><li><span style="font-style: italic;">Input/Ground/Ouput pinning</span>: use LM3940, LF33V. See Jaluino v1.1a.</li><li><span style="font-style: italic;">Ground/Output/Input pinning</span>: use LD1117V33, LM1117T, LM1086. See Jaluino v1.1b.</li></ul><li><span style="font-weight: bold;">More space between connector shields</span>. Last version revealed space between shield connectors weren't big enough, you couldn't put a mini-breadboard between them. This time, connectors have more space, slightly more than original Arduino's.</li></ul>(also, because Richard, who designed the board, doesn't like vias, he removed one :))<br /><br /><span style="font-weight: bold;font-size:130%;" >Schematics and PCBs<br /></span><br /><ul><li><span style="font-weight: bold;">Jaluino v1.1a</span>: <span style="font-style: italic;">Input/Ground/Ouput pinning</span>, using LM3940 or LF33V. See <a href="http://jallib.googlecode.com/svn/trunk/project/jaluino/schematics/jaluino_medium_v12.pdf">schematic</a> and <a href="http://jallib.googlecode.com/svn/trunk/project/jaluino/schematics/jaluino_medium_v12_pcb.pdf">PCB</a>.</li><li><span style="font-weight: bold;">Jaluino v1.1b</span>: <span style="font-style: italic;">Ground/Output/Input pinning</span>, using LD1117V33, LM1117T or LM1086. See <a href="http://jallib.googlecode.com/svn/trunk/project/jaluino/schematics/jaluino_medium_v11.pdf">schematic</a> and <a href="http://jallib.googlecode.com/svn/trunk/project/jaluino/schematics/jaluino_medium_v11_pcb.pdf">PCB</a>.</li></ul><span style="font-style: italic;">Note: by the time of writing, files are being renamed, in any case, go to Jaluino directory <a href="http://code.google.com/p/jallib/source/browse/trunk/project/jaluino/schematics/">here</a>, and select the appropriate files. Eventually, there will be one version remaining, to keep the whole thing simple...)</span><br /><br /><br /><span style="font-weight: bold;font-size:130%;" >Results...<br /></span><br />Here are couples of photos showing the results. The version built is Jaluino v1.1b, expecting to use LM1086 3.3V regulator. But that doesn't make a difference, since I'm still waiting to receive the part :). So note there's no 3.3V regulator on the board, yet it's working with 5V...<br /><br />(this is not the best board I built, I had quite some problems mostly due to my etchant being too saturated, so expect the more beautiful board next time !)<br /><br /><br /><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6eJp-t1YPFbIMnMd-zFjtKuwpbo_vP5gFjH2ECN2pM8ezRX9CN88icSBhRIOEPmYNQj9EUiYQi09M5wmyTzV4fhQ4Tx8oEtZ3CRDAQTtEkk13ktPm0U7yB3SPBYE4PzXrCbivNAJAao0/s1600-h/components.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6eJp-t1YPFbIMnMd-zFjtKuwpbo_vP5gFjH2ECN2pM8ezRX9CN88icSBhRIOEPmYNQj9EUiYQi09M5wmyTzV4fhQ4Tx8oEtZ3CRDAQTtEkk13ktPm0U7yB3SPBYE4PzXrCbivNAJAao0/s400/components.jpg" alt="" id="BLOGGER_PHOTO_ID_5378789350009372162" border="0" /></a><span style="font-style: italic;">Most components used to build Jaluino v1.1, except LM1086 and few caps<br /><br /><br /></span></div><br /><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsBLtp7LIKLxN6C8VvxPh4eZ2xwMOjh9nhXNyANEk_fCqfIfUt8PstBis2TRNpLqNA3VGtWbZzTFrpGK7tYCpJrqM98YuJXRYZGG5SbUwx2kSI8OEyKMZDpqFVsAtvbmdsRuV5jtpul1g/s1600-h/jaluinov1.1.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsBLtp7LIKLxN6C8VvxPh4eZ2xwMOjh9nhXNyANEk_fCqfIfUt8PstBis2TRNpLqNA3VGtWbZzTFrpGK7tYCpJrqM98YuJXRYZGG5SbUwx2kSI8OEyKMZDpqFVsAtvbmdsRuV5jtpul1g/s400/jaluinov1.1.jpg" alt="" id="BLOGGER_PHOTO_ID_5378789605653518338" border="0" /></a><span style="font-style: italic;">Jaluino v1.1 is born !</span><br /></div><br /><br /><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9fGPYfNS9Sy1BwdzJmW0daRqwV2qKdPTAFHsZTe1uoRr1McOtKbaxwMFHn5ijkJ2qpmhcuUcoJWrLjrnwrx4VhjM_NOpFzcAfu7nvsOYcsw_2B8kyLeFFIJiZSqs0655-Y52qNkAGCpw/s1600-h/copper_side.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9fGPYfNS9Sy1BwdzJmW0daRqwV2qKdPTAFHsZTe1uoRr1McOtKbaxwMFHn5ijkJ2qpmhcuUcoJWrLjrnwrx4VhjM_NOpFzcAfu7nvsOYcsw_2B8kyLeFFIJiZSqs0655-Y52qNkAGCpw/s400/copper_side.jpg" alt="" id="BLOGGER_PHOTO_ID_5378789357169381746" border="0" /></a><span style="font-style: italic;">(ugly) Copper side<br /><br /><br /></span><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgps-Co5I5ZyGdTnIbsMHtgVYkJka6LFA1Rt7I9U2CDwYzgsgQ-DCTKZe4joixYUzdlTpSpkzq7bZxG8JfFVGQSmA6RBJcpWzWbMnWBQgIRhXU26pWILMcNVpRxnWAHjU59yYqwLG0KRQc/s1600-h/com_connectors.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgps-Co5I5ZyGdTnIbsMHtgVYkJka6LFA1Rt7I9U2CDwYzgsgQ-DCTKZe4joixYUzdlTpSpkzq7bZxG8JfFVGQSmA6RBJcpWzWbMnWBQgIRhXU26pWILMcNVpRxnWAHjU59yYqwLG0KRQc/s400/com_connectors.jpg" alt="" id="BLOGGER_PHOTO_ID_5378789336915478114" border="0" /></a><span style="font-style: italic;">Connectors, from left to right: USB, serial, i²c and ICSP<br /><br /><br /></span><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkbBebPkCrZRsq1SjB2q9iC7cCh2Tvz64eA8l7D3i4jPt_jnLWXzq2R2GeXACavnYA6iFZ-A48M1R1eYi9wmbDA56H8WQv2J-V_ioxIIu6vBE8e-3jV2bSz57D_p2fCKUIxfh9m0c7xKE/s1600-h/jaluino_plus_xwisp2.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkbBebPkCrZRsq1SjB2q9iC7cCh2Tvz64eA8l7D3i4jPt_jnLWXzq2R2GeXACavnYA6iFZ-A48M1R1eYi9wmbDA56H8WQv2J-V_ioxIIu6vBE8e-3jV2bSz57D_p2fCKUIxfh9m0c7xKE/s400/jaluino_plus_xwisp2.jpg" alt="" id="BLOGGER_PHOTO_ID_5378789587669669778" border="0" /></a><span style="font-style: italic;">Jaluino v1.1 and Wisp648, programming step<br /><br /><br /></span><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhB59mfhfwBT4YMN9gQcuxP6kNaZdyUkKULex1blNAl1aKclYYXJMtWXo3ox1fzmJelH2fwlX_K_hVQduwuH2aNMtow1VOFLm163Ybf-w40qIj263Gtm5cJamYj9ZVCWsE6_RZc5O2XoRU/s1600-h/xwisp_connector.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhB59mfhfwBT4YMN9gQcuxP6kNaZdyUkKULex1blNAl1aKclYYXJMtWXo3ox1fzmJelH2fwlX_K_hVQduwuH2aNMtow1VOFLm163Ybf-w40qIj263Gtm5cJamYj9ZVCWsE6_RZc5O2XoRU/s400/xwisp_connector.jpg" alt="" id="BLOGGER_PHOTO_ID_5378789718208519778" border="0" /></a><span style="font-style: italic;">Wisp648 can directly be connected to Jaluino ISCP connector, making easy to program chip on-board<br /><br /><br /></span><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkVjBypbuMDy4wJOdchWQAxPkiP_wPpU0QgVoF00rVAHYPVowzgUHC5wpdl_pJI7MDaG4keaLAqu0BOEUcqhz4aFiKZIfMF2B4d_l-1-VSh6yirXNOY2QKu_I0r-TViC9-EtC2uOb02PM/s1600-h/jaluino_plus_xwisp2_again.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkVjBypbuMDy4wJOdchWQAxPkiP_wPpU0QgVoF00rVAHYPVowzgUHC5wpdl_pJI7MDaG4keaLAqu0BOEUcqhz4aFiKZIfMF2B4d_l-1-VSh6yirXNOY2QKu_I0r-TViC9-EtC2uOb02PM/s400/jaluino_plus_xwisp2_again.jpg" alt="" id="BLOGGER_PHOTO_ID_5378789595675045634" border="0" /></a><span style="font-style: italic;">Another one :)<br /><br /><br /></span><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1XqsV-zXt04gAps-HT5E3VaFdwuus5O0soPHyCsBDTsQQneUBU-mZc7LOXoaw8LRdFZSj6lEQ9qtBTKbEoI5JnLel8nKuuUsG0lmIHPl2IEMCuQVTbTGtQ9MDOkSHXPab9hKJoCKh9lQ/s1600-h/blink-a-led.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1XqsV-zXt04gAps-HT5E3VaFdwuus5O0soPHyCsBDTsQQneUBU-mZc7LOXoaw8LRdFZSj6lEQ9qtBTKbEoI5JnLel8nKuuUsG0lmIHPl2IEMCuQVTbTGtQ9MDOkSHXPab9hKJoCKh9lQ/s400/blink-a-led.jpg" alt="" id="BLOGGER_PHOTO_ID_5378789324458040434" border="0" /></a><span style="font-style: italic;">Jaluino v1.1, blinking a LED (while waiting for a development shield...)<br /><br /><br /></span><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi57aGGS2au_wHwcmzmnCBgZp_Giq-98kySsEATmOqDA1Oh8A5eajlQQyvo1fMx4Rghl2xRGGtz_1TJc85NG2RYBz_r2TUn-OCjOVkDHSwBYgc03UZtG5fZpBqI4bLEbPYQ-_FjcSfRb3E/s1600-h/power_connector.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi57aGGS2au_wHwcmzmnCBgZp_Giq-98kySsEATmOqDA1Oh8A5eajlQQyvo1fMx4Rghl2xRGGtz_1TJc85NG2RYBz_r2TUn-OCjOVkDHSwBYgc03UZtG5fZpBqI4bLEbPYQ-_FjcSfRb3E/s400/power_connector.jpg" alt="" id="BLOGGER_PHOTO_ID_5378789610163254322" border="0" /></a><span style="font-style: italic;">Power connector supplies the breadboard with +5V<br /><br /><br /></span><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLyICZ5zKKCIMYci7o1oGJaI_y8iChr_QTJe8hiqRGjpRr5MWqmcQFg-m7h0sg0s4QD98JWPGEupWvWlQk24HmimnWop1tGzjaNpXURSgJdpzpFpmbVDZSs6aQPlH3MWxOEdNRf4U6Oy4/s1600-h/ra0_connector.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLyICZ5zKKCIMYci7o1oGJaI_y8iChr_QTJe8hiqRGjpRr5MWqmcQFg-m7h0sg0s4QD98JWPGEupWvWlQk24HmimnWop1tGzjaNpXURSgJdpzpFpmbVDZSs6aQPlH3MWxOEdNRf4U6Oy4/s400/ra0_connector.jpg" alt="" id="BLOGGER_PHOTO_ID_5378789619848853714" border="0" /></a><span style="font-style: italic;">LED is connected to RA0, a wire is used to connect this pin to the breadboard<br /><br /><br /></span><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYVNc_k7dkJ5OxleDSJVmjSgmlNMOXnwVzuAJOKnKrJB16XCun8TG7iiQpHjF9N5n9WToHqYeUGnaeD6iwNe5ff1uMDb0KtiSxXhlUHTR9Qabf9Os6iksB9d5lNF4Myuutax3HRM3627U/s1600-h/breadboard.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYVNc_k7dkJ5OxleDSJVmjSgmlNMOXnwVzuAJOKnKrJB16XCun8TG7iiQpHjF9N5n9WToHqYeUGnaeD6iwNe5ff1uMDb0KtiSxXhlUHTR9Qabf9Os6iksB9d5lNF4Myuutax3HRM3627U/s400/breadboard.jpg" alt="" id="BLOGGER_PHOTO_ID_5378789334250522066" border="0" /></a><span style="font-style: italic;">Breadboard view...<br /><br /><br /></span><div style="text-align: left;"><span style="font-style: italic;"></span>So... I need to "practice" this new Jaluino v1.1 board. Next steps are:<br /><ul><li><span style="font-weight: bold;">documentation</span>, explaining, for instance, how to use jumpers, etc...</li><li><span style="font-weight: bold;">tutorials</span>, showing how to use the board, with jalv2 & jallib (please provide some suggestions about covered topics)</li><li><span style="font-weight: bold;">shields building</span>, an <span style="font-style: italic;">intermediate shield</span> acting as a converter between Jaluino's and Arduino's original shields, and a <span style="font-style: italic;">development shield</span>, to experiment with LCD, ADC, PWM, sounds, buttons, ... Any more suggestions ?<br /></li></ul><br /><br /><span style="font-style: italic;">Sébastien Lelong & Richard Zengerink</span><br /><span style="font-style: italic;"></span></div></div>Sebastien Lelonghttp://www.blogger.com/profile/00317258446230687333noreply@blogger.com3tag:blogger.com,1999:blog-8299212346186005351.post-60627134035299690732009-08-25T19:41:00.022+02:002010-01-03T11:00:19.473+01:00Building Jaluino v1.0<div style="text-align: center;"><span style="color: rgb(102, 0, 0); font-weight: bold;">Jaluino, with user guide, schematics, PCB, shields, etc... can now be reached on the following sites:</span><br /><br /><span style="font-weight: bold;">Main site</span>: <a href="http://jaluino.org/">http://jaluino.org</a><br /><span style="font-weight: bold;">Repository</span>: <a href="http://jaluino.googlecode.com/">http://jaluino.googlecode.com</a><br /><span style="font-weight: bold;">Group</span>: <a href="http://groups.google.com/group/jaluino">http://groups.google.com/group/jaluino</a><br /></div><br /><br /><br /><br />Big time.<br /><br />Thanks to <a href="http://groups.google.com/group/jallib/browse_thread/thread/7167209cf4a35042/8a13f3685feff506?lnk=gst&">Richard's last contribution</a>, we now have a nice schematics for the first version of <span style="font-weight: bold;">Jaluino board</span>, and very clean and easy to build PCB.<br /><br /><span style="font-weight: bold;">Jaluino</span> is aimed to be a <span style="font-weight: bold;">clone of Arduino</span>, but PIC-based, and powered by <span style="font-weight: bold;">jalv2 & jallib</span>. The purpose is to share a <span style="font-style: italic;">common hardware configuration</span>, on top of which one can add different features and capabilities, thanks to shields (daughter boards). Ala Arduino...<br /><br />This post is to give an overview of how to build it, but with not so much details. If you want to build it, you'll have to be familiar with PCB creation.<br /><br />That said, having this board within your hands is really nice ! It really helps thinking about what could be done with it, what could be improved, and is a nice base to start thinking about building shields.<br /><br />So, here we go ! First of all, you can find all schematics, PCB and many more details in jallib SVN repository, under "<a href="http://code.google.com/p/jallib/source/browse/trunk/project/jaluino/#jaluino/schematics">/project/jaluino</a>" directory.<br /><br />Here's the <span style="font-weight: bold;">schematic</span>, but have a look at the <a href="http://jallib.googlecode.com/svn/trunk/project/jaluino/schematics/jaluino_medium.pdf">PDF file</a> for a more detailed one:<br /><br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgk2Fp4F_v6V_4HR21pcPOo0qa6BupGDJrpi7RJg7PRZ7Erh9vmjWcCTS9aYvVNUeUxE3-w1lllvbTrcfgjJbLys_uTJlcSIctanr02itZwW-hLf_oo7_GHfn8lsoOnNCQB2wHls6zT1P4/s1600-h/schematic.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 283px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgk2Fp4F_v6V_4HR21pcPOo0qa6BupGDJrpi7RJg7PRZ7Erh9vmjWcCTS9aYvVNUeUxE3-w1lllvbTrcfgjJbLys_uTJlcSIctanr02itZwW-hLf_oo7_GHfn8lsoOnNCQB2wHls6zT1P4/s400/schematic.png" alt="" id="BLOGGER_PHOTO_ID_5373961506747944658" border="0" /></a><br /><br />The <span style="font-weight: bold;">PCB</span> is surprisingly very simple (thanks Richard !), and thus very to easy to build:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJushAq-CvUb6JrJN_fgRiJTIvxj_PA28UGsLFVFnLq-lacqrAf0RH18xpe3I44F1Bd8bauau0UEMwA4pHuKq4julOKoAjjBRA0kYB_UQTZVS9RN71-ybM4iyDJOWGbfjtqsIbzh_KBfU/s1600-h/pcb.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 298px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJushAq-CvUb6JrJN_fgRiJTIvxj_PA28UGsLFVFnLq-lacqrAf0RH18xpe3I44F1Bd8bauau0UEMwA4pHuKq4julOKoAjjBRA0kYB_UQTZVS9RN71-ybM4iyDJOWGbfjtqsIbzh_KBfU/s400/pcb.png" alt="" id="BLOGGER_PHOTO_ID_5373961786434227058" border="0" /></a><br /><span style="font-style: italic;">Don't print and use this image ! Use the <a href="http://jallib.googlecode.com/svn/trunk/project/jaluino/schematics/jaluino_medium_pcb.pdf">PDF file here</a>, and print it at scale 1:1, that is, without any zoom-out or zoom-in correction. If any doubt, once printed, put the microcontroller support on the paper (or the like) and check all pins perfectly fit all holes.</span><br /><br /><br /><span style="font-weight: bold;font-size:130%;" >PCB creation<br /><br /></span><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimhMiAYSnUcfO9vIbt1aEtMZ4VjYcQ5z-9jWu9B53qHKz1Oow0FeeSsfATfGXGpxDajsUoSVKD8du-MtIRsRiLCKP7yzzquD0A2BgSn-bAYGXLC16V8fPgIVTxSWptWJeSpWXPitf4iNg/s1600-h/01_paper.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimhMiAYSnUcfO9vIbt1aEtMZ4VjYcQ5z-9jWu9B53qHKz1Oow0FeeSsfATfGXGpxDajsUoSVKD8du-MtIRsRiLCKP7yzzquD0A2BgSn-bAYGXLC16V8fPgIVTxSWptWJeSpWXPitf4iNg/s400/01_paper.jpg" alt="" id="BLOGGER_PHOTO_ID_5373963068236616002" border="0" /></a><br />As said, PCB creation is easy. I use the <span style="font-style: italic;">toner transfert method</span>, using <span style="font-style: italic;">glossy photo laser paper</span> (dedicated to laser printer, not ink-jet). If interested, have a look at <a href="http://sirloon.net/loonaweb/sirblog/pcb-using-toner-transfer-method-comparison">this post</a>, explaining how to do this, step by step, with a video.<br /><br /><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxxMfWR9xHBAz-zl8KXUPoY1J7MJymDcfwkfz-0HL1aWsuKbGU6mlEpjgVaK59YebfVFTqtHSyyYDD-7-zHb6_DgH2AACN57iA3ECEnx6qf6uuO3DcEpplKcxrxkGehncEBe37h58IGUY/s1600-h/02_to_etch.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxxMfWR9xHBAz-zl8KXUPoY1J7MJymDcfwkfz-0HL1aWsuKbGU6mlEpjgVaK59YebfVFTqtHSyyYDD-7-zHb6_DgH2AACN57iA3ECEnx6qf6uuO3DcEpplKcxrxkGehncEBe37h58IGUY/s400/02_to_etch.jpg" alt="" id="BLOGGER_PHOTO_ID_5373963072930384562" border="0" /></a><span style="font-style: italic;">Once the transfert is done, the PCB is ready to be etched.<br /><br /></span><div style="text-align: center;"><span style="font-style: italic;"><span style="font-style: italic;"></span></span></div></div><br /><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-hrLvr8AilTV-z9tscSnqE0mDf43U-yqeswy_8yAxGFx80gNQ6Hdlzpr-mOzkxlUg91Lw4TOY7nt5rHaSqWkyKVad_j6gfmXt8O7U7R4Bn0PAn5pcxZo_6SKWoqdPa_Z3WX00ky76fNs/s1600-h/04_drill.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 300px; height: 400px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-hrLvr8AilTV-z9tscSnqE0mDf43U-yqeswy_8yAxGFx80gNQ6Hdlzpr-mOzkxlUg91Lw4TOY7nt5rHaSqWkyKVad_j6gfmXt8O7U7R4Bn0PAn5pcxZo_6SKWoqdPa_Z3WX00ky76fNs/s400/04_drill.jpg" alt="" id="BLOGGER_PHOTO_ID_5373963710082166530" border="0" /></a><span style="font-style: italic;">PCB is etched, now drill the holes</span><br /><br /></div><br /><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWh9VnjTX3_f4FmwWYNbWErgAjHfDyk5r4g8rUww-azEhqNRPBRbA6I1EkTjtmTeFmf_cpRRAyOyGYuSYi_JVkQuyvr5u8DCmHzlLdoP-3W5hApsWDcx8jUW8mhj1nb2OVhogQOIAgWpc/s1600-h/03_etched.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWh9VnjTX3_f4FmwWYNbWErgAjHfDyk5r4g8rUww-azEhqNRPBRbA6I1EkTjtmTeFmf_cpRRAyOyGYuSYi_JVkQuyvr5u8DCmHzlLdoP-3W5hApsWDcx8jUW8mhj1nb2OVhogQOIAgWpc/s400/03_etched.jpg" alt="" id="BLOGGER_PHOTO_ID_5373963079827472818" border="0" /></a><span style="font-style: italic;">PCB is ready for soldering</span><br /></div><br /><br /><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimKlO2uVWt-XZLfRI6CmNZ523hBx-wey9ZHTQjj_zfpuJ0CZ20HWrglc4-EJBnSL9Iy1u9Kii3FzeOde9pT1AbXh6c_YvDAC8kpsA-1n2Tx6XAVZSsfJqWjTRp53xVlNchYDrW3tkC7E8/s1600-h/05_compare.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimKlO2uVWt-XZLfRI6CmNZ523hBx-wey9ZHTQjj_zfpuJ0CZ20HWrglc4-EJBnSL9Iy1u9Kii3FzeOde9pT1AbXh6c_YvDAC8kpsA-1n2Tx6XAVZSsfJqWjTRp53xVlNchYDrW3tkC7E8/s400/05_compare.jpg" alt="" id="BLOGGER_PHOTO_ID_5373964381079673858" border="0" /></a><span style="font-style: italic;">A brief comparison between original Arduino and Jaluino. Jaluino is obsviously bigger, but embed a much bigger chip, and most importantly is made homebrew!</span><br /></div><br /><span style="font-weight: bold;font-size:130%;" ><br />Soldering components</span><br /><br />I try to start soldering components from the smaller & lower ones, to the biggest and taller ones. We'll follow this <span style="font-weight: bold;">component diagram</span>, provided in PCB PDF file (page 2).<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhx5gytbC_MLsYz3brgAfl5UCIpKuSGRRwDehYN0JlaJVKy3UMp2vkkIvttdme_Za7sFhvOkv4lBasUeZC4G1tXi4KAKqFnFggSQ11XH7KS2PiSxrjtT2teR5ZWkm1FBCxmyF8p5EGlJ0U/s1600-h/parts.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 293px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhx5gytbC_MLsYz3brgAfl5UCIpKuSGRRwDehYN0JlaJVKy3UMp2vkkIvttdme_Za7sFhvOkv4lBasUeZC4G1tXi4KAKqFnFggSQ11XH7KS2PiSxrjtT2teR5ZWkm1FBCxmyF8p5EGlJ0U/s400/parts.png" alt="" id="BLOGGER_PHOTO_ID_5373961789734920130" border="0" /></a><br /><br /><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEIKfAd3Ngb9eDsIhqIAqXZHseI3cVXtS_vY32mrzsb9DGGGH0KGXJKA0DfEb9kfzcg6ytDHpA8A4znxMUSYElblTCirggnmEmGYOU5yWciJLH6ViLhmnU2AoWsIBuIUH7xAI9obS6GUU/s1600-h/06_res_diodes.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEIKfAd3Ngb9eDsIhqIAqXZHseI3cVXtS_vY32mrzsb9DGGGH0KGXJKA0DfEb9kfzcg6ytDHpA8A4znxMUSYElblTCirggnmEmGYOU5yWciJLH6ViLhmnU2AoWsIBuIUH7xAI9obS6GUU/s400/06_res_diodes.jpg" alt="" id="BLOGGER_PHOTO_ID_5373965351196436034" border="0" /></a><span style="font-style: italic;">First solder resistors and diodes</span><br /></div><br /><br /><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhn3-sFemjIjYusBcql05CC-cFDb278JgKiX3jzi8d6UdTWJJSpJORARviSg5KoLGeY6MJYiS1tzQ3lvOy_dWrwqbSljOuidquaJv7br5S41Qr3PRryK-FQFxOfcJPpwbZlF2HagN-VG44/s1600-h/07_smallcaps.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhn3-sFemjIjYusBcql05CC-cFDb278JgKiX3jzi8d6UdTWJJSpJORARviSg5KoLGeY6MJYiS1tzQ3lvOy_dWrwqbSljOuidquaJv7br5S41Qr3PRryK-FQFxOfcJPpwbZlF2HagN-VG44/s400/07_smallcaps.jpg" alt="" id="BLOGGER_PHOTO_ID_5373965355000856850" border="0" /></a><span style="font-style: italic;">Then solder small capacitors (unpolarized)</span><br /></div><br /><br /><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNdJiuV5v_YasQzQk3KMS-AZ3kcv2si50ODQX_S2O4WOJJRXz_5ra1bTs9TubYDBJsAm6F_hyphenhypheneO6tziGT-lUozLZ07WgJXd5tn7CwdS3OgpMA-ay8DHn0OBreA5gm1VriIaqut5kr-Mos/s1600-h/08_tulipe.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNdJiuV5v_YasQzQk3KMS-AZ3kcv2si50ODQX_S2O4WOJJRXz_5ra1bTs9TubYDBJsAm6F_hyphenhypheneO6tziGT-lUozLZ07WgJXd5tn7CwdS3OgpMA-ay8DHn0OBreA5gm1VriIaqut5kr-Mos/s400/08_tulipe.jpg" alt="" id="BLOGGER_PHOTO_ID_5373965363900510866" border="0" /></a><span style="font-style: italic;">Place microcontroller support, quartz, pushbutton and bridge rectifier (I used a DF02M instead of DF04M)</span><br /><br /><br /></div><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEC8MsbMpbhM0FcrLfeiKfAVW8A1Emppj7jCu_gNPPAnI8L7HXnEZV7ImbqNBVgBbX8NVnWyQ_iGzRCG7luK-MgStUmzQf057x7ht3jdkb9edhMJfdZSc3h_bWPr14FrSnduK9xaPjNkQ/s1600-h/09_wire_jack.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEC8MsbMpbhM0FcrLfeiKfAVW8A1Emppj7jCu_gNPPAnI8L7HXnEZV7ImbqNBVgBbX8NVnWyQ_iGzRCG7luK-MgStUmzQf057x7ht3jdkb9edhMJfdZSc3h_bWPr14FrSnduK9xaPjNkQ/s400/09_wire_jack.jpg" alt="" id="BLOGGER_PHOTO_ID_5373965368403913442" border="0" /></a><span style="font-style: italic;">Add wires (green), power jack, big capacitors (polarized)</span><br /></div><br /><br /><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJgD9Vb0AgOBgRMyiGh3gZr468ezwGomgzjaKuXUpRTmgK6DlpivLcdL1159uxohfud7D7sMk62QvwkimzVD4Q9sEHvSYEmxA7TsTW72DRIR4yg1IE1kxiP86keYxz_fX1U70Ky5WcPk0/s1600-h/10_connectors.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJgD9Vb0AgOBgRMyiGh3gZr468ezwGomgzjaKuXUpRTmgK6DlpivLcdL1159uxohfud7D7sMk62QvwkimzVD4Q9sEHvSYEmxA7TsTW72DRIR4yg1IE1kxiP86keYxz_fX1U70Ky5WcPk0/s400/10_connectors.jpg" alt="" id="BLOGGER_PHOTO_ID_5373965369892508306" border="0" /></a><span style="font-style: italic;">Solder shield connectors, serial and ICP connects. Add 7805 voltage regulator. Don't forget jumper for power selection and RTS reset feature.</span><br /></div><br /><br /><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmoTH9LP5D0wxkqWYfTW_k0o0U_USQyHZtPnRPc2aU45UqLmUIjk0YTx8gmrTLpP0eZamD0DLQYhw-xh0G0HwKDRxNuOY48NHJpAwRpdTeFSJy7ah7zV6I-P6L0luyyuW9ENGGbesFc80/s1600-h/11_usb_fuse.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmoTH9LP5D0wxkqWYfTW_k0o0U_USQyHZtPnRPc2aU45UqLmUIjk0YTx8gmrTLpP0eZamD0DLQYhw-xh0G0HwKDRxNuOY48NHJpAwRpdTeFSJy7ah7zV6I-P6L0luyyuW9ENGGbesFc80/s400/11_usb_fuse.jpg" alt="" id="BLOGGER_PHOTO_ID_5373966546900502674" border="0" /></a><span style="font-style: italic;">Place USB connector and fuse support</span><br /></div><br /><br /><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAAOa7Aw23gyb80k7cxLmo0NCndKH8DiJ84-d8v4Te7nXh3zYnCAT1wik6Rq3-Ssxs53HrjM6t1yc51ZPjWv1dBxg25qV5ixsKTyQ5vWiV2uyDyXDYwl1vitaCpIHmPbV-TzwBmEHuxYk/s1600-h/12_done.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAAOa7Aw23gyb80k7cxLmo0NCndKH8DiJ84-d8v4Te7nXh3zYnCAT1wik6Rq3-Ssxs53HrjM6t1yc51ZPjWv1dBxg25qV5ixsKTyQ5vWiV2uyDyXDYwl1vitaCpIHmPbV-TzwBmEHuxYk/s400/12_done.jpg" alt="" id="BLOGGER_PHOTO_ID_5373966552006027650" border="0" /></a><span style="font-style: italic;">Place your favorite 18F4550 onto the support, and don't forget the fuse ! You're done, kudos !</span><br /></div><br /><br /><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi91Ajr1w-P6V_jZe9BjqfDiaYHw930Yt26OIt0lMOuDTMCO7QAy53_0DyRvtodWCrQA-WXcArwTHBN_JOk7F7tDD_-MVkvW-Jw9LFoAArtWaqqK4erMFq-CyFzmZF49nZEyhd0TJIWzTk/s1600-h/13_verso.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi91Ajr1w-P6V_jZe9BjqfDiaYHw930Yt26OIt0lMOuDTMCO7QAy53_0DyRvtodWCrQA-WXcArwTHBN_JOk7F7tDD_-MVkvW-Jw9LFoAArtWaqqK4erMFq-CyFzmZF49nZEyhd0TJIWzTk/s400/13_verso.jpg" alt="" id="BLOGGER_PHOTO_ID_5373966559041552178" border="0" /></a><span style="font-style: italic;">The reverse side...</span><br /></div><br /><br />Now here's a brief map showing the <span style="font-weight: bold;">different features</span> coming with this board.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEie3EVhS9Kwn9DZvetMhIF6pt6wFK37eGX-_no8H7vdoFBKehxtGFOsdx4WtV_ICVsSVHUbthk5V1_1gE41_sxJPCEv0ahroeYdKZxciHJmei_Y0ZilPLboxF41_YCA2IGDE7ad9lfjc58/s1600-h/jaluino_map.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 224px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEie3EVhS9Kwn9DZvetMhIF6pt6wFK37eGX-_no8H7vdoFBKehxtGFOsdx4WtV_ICVsSVHUbthk5V1_1gE41_sxJPCEv0ahroeYdKZxciHJmei_Y0ZilPLboxF41_YCA2IGDE7ad9lfjc58/s400/jaluino_map.png" alt="" id="BLOGGER_PHOTO_ID_5373971337210733586" border="0" /></a><br /><span style="font-style: italic;">Note: one important missing feature is I²C support, which surely will come in the next version</span>.<br /><br />I already tried quite few things with this board: <span style="font-style: italic; font-weight: bold;">In Circuit Programming</span> using XWisp648, <span style="font-style: italic; font-weight: bold;">blinking a LED</span> (of course), <span style="font-style: italic; font-weight: bold;">UART</span> using serial connector, with <span style="font-style: italic; font-weight: bold;">tinybootloader</span> and testing <span style="font-style: italic; font-weight: bold;">Reset-via-RTS</span> feature (great), and <span style="font-style: italic;"><span style="font-weight: bold;">USB-to-seria</span>l</span> ! In the next post, I'll try to describe these experiments one by one.<br /><br />Another important thing, if not <span style="font-style: italic;">the</span> crucial one, is how big should a shield board must be. Current shield connectors configuration gives a surface closed to Arduino's (only considering the surface between connectors, not the whole board). It it <span style="font-style: italic;">enough</span> ? Should a shield board be bigger ? Now imagine this board is <span style="font-style: italic;">doubled-sided</span>, built through a <span style="font-style: italic;">professional process </span>(and thus available as a commercial product). How much smaller would it be ? Will current connectors configuration be valid ? This is a very important thing, because from this is derived all the shield compatibility. If one builds a shield for this Jaluino v1.0, and shield connectors gets changed, this shield will have to be adapted and rebuilt...<br /><br />And about shields, now the time has come to design a development shield, providing (more or less) basic features. This shield could be used to learn jalv2 & jallib. I was thinking about having:<br /><ul><li>one LED connected to a standard digital output</li><li>one LED connected to a PWM channel<br /></li><li>maybe a buzzer connected to the other PWM channel to make sounds<br /></li><li>one or two push-buttons (input)<br /></li><li>pot to have fun with ADC</li><li>maybe an EEPROM to play with I²C</li><li>a small LCD screen (8x2)</li></ul>But maybe that's a little bit too much for single shield...<br /><br /><br />Please advise !<br /><br /><br /><br /><span style="font-style: italic;">Sébastien Lelong & Richard Zengerink.</span>Sebastien Lelonghttp://www.blogger.com/profile/00317258446230687333noreply@blogger.com6tag:blogger.com,1999:blog-8299212346186005351.post-6592004162285707572009-08-10T23:57:00.009+02:002009-08-11T00:53:01.558+02:00PIC 18f14k50 based USB WISP programmer<div><span class="Apple-style-span" style="font-size: large;"><b>Introduction</b></span></div>Today the description of a USB WISP programmer. A while back I had some trouble with my ICD2 clone, therefore I decided to make a WISP programmer. Since I've written the USB libraries for JAL(lib) and because I just had ordered a tube of 10 PIC18f14k50, I decided to redesign the original WISP so it uses the PIC18f instead of the the PIC16f648 (which I did not have in my junk box), and use the USB-Serial library so I can still use the various host applications but I can plug it in directly to the USB port. The additional benifits are:<div><br /></div><div><ul><li>Very cheap (just a PIC18f14k50 + resistor and capacitors, total costs ~5 Euro)</li><li>Have a fast serial connection</li><li>Can use exsisting WISP host applications (like Rob's XWISP2)</li><li>Can be directly powered from the USB port (no external power supply needed)</li><li>When adding a 3.3V regulator, board can also be used to program LF devices (if Vpp = 9v)</li><li>Added an additional connector for future use, like JTAG & I2C and RS-232 TTL</li></ul></div><div><br /></div><div>The schematic is very straigtforward, the blue boxed areas contain the optional section of the USB WISP programmer</div><div><br /></div><div><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9J0yy-_9C_22XCzZSU1mj2nPGGR90WensMlmyg5hGbnktZhkmbZgE5YUQMhYF9WDJL7ihR9nkekmTctcbD5y-Uxe2WxS69cwVYLUFUINLH0VSjqmgYaV7FKyJ-_egw7rp7-LMQYaUjlw2/s1600-h/usb_wisp_schematic.PNG"><img style="cursor:pointer; cursor:hand;width: 400px; height: 275px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9J0yy-_9C_22XCzZSU1mj2nPGGR90WensMlmyg5hGbnktZhkmbZgE5YUQMhYF9WDJL7ihR9nkekmTctcbD5y-Uxe2WxS69cwVYLUFUINLH0VSjqmgYaV7FKyJ-_egw7rp7-LMQYaUjlw2/s400/usb_wisp_schematic.PNG" border="0" alt="" id="BLOGGER_PHOTO_ID_5368461632070507362" /></a><br /><br /></div><div><br /></div><div>I've made a few modifications to the original design, first the Target power is controlled by a PNP transistor, which acts as switch (so target power can be turned on/off), because USB 5v does not like to be short circuited for a short period, as is done in the WISP 648. In addition I've added a PNP transistor to control the Target VPP line, this is for future use.</div><div><br /></div><div> I also made a small PCB, however, Wouter van Ooijen (the designer of the Wisp 648 programmer, see <a href="http://www.voti.nl">www.voti.nl</a>) asked me not to publish the PCB layout. So don't ask me for it, if you want to build this project you have to design you own PCB, if you can't, buy a Wisp 648 kit from Wouter. The assembled PCB is depicted below:</div><div><br /></div><div><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2jJ887g6vYvC9O8kDsjcqNHtiguV7NlYVEdnsEUb0Sv8Yr0XIkXH_JCLzUPf8_p_wnRKF7d_nv_8B4C5Q1_tnUIjy7OdS3ga5V5agFPb7YHHt8Gsclpg0ie6r8zbXw8PsWUy0nuJU_iS-/s1600-h/usb_wisp_pcb_assembled.JPG"><img style="cursor:pointer; cursor:hand;width: 400px; height: 247px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2jJ887g6vYvC9O8kDsjcqNHtiguV7NlYVEdnsEUb0Sv8Yr0XIkXH_JCLzUPf8_p_wnRKF7d_nv_8B4C5Q1_tnUIjy7OdS3ga5V5agFPb7YHHt8Gsclpg0ie6r8zbXw8PsWUy0nuJU_iS-/s400/usb_wisp_pcb_assembled.JPG" border="0" alt="" id="BLOGGER_PHOTO_ID_5368464249002643282" /></a><br /></div><div><br /></div><div><span class="Apple-style-span" style="font-size: large;"><b>The Source code</b></span></div><div>I just made minor modifications to the original source code (see www.voti.nl). The changes are:</div><div><ul><li>Include usb_serial library</li><li>Change UART functions, so they send and receive chars from the USB library</li><li>Tune the timing delays (becuase effective speed is raised from 20->48 MHz)</li><li>Had to adapt the HEX<->ASCII function, because the original code still uses some inline assembly which did not work properly for the PIC18f</li><li>Call USB-Flush in the main routing</li></ul></div><div><br /></div><div>There still some work left, i.e. the port trough function is not working yet, the advantage of this design is the the UART can be used (even the polarity inversion of the UART signals can be programmed with the PIC18f14k50), so pass trough can work with speeds up to 115200 baud.</div><div>The JAL source code is uploaded in the JALLIB google code file download section, <a href="http://groups.google.com/group/jallib/files">http://groups.google.com/group/jallib/files</a> </div><div><br /></div><div><span class="Apple-style-span" style="font-size: large; "><b>Results</b></span></div><div>The USB Wisp is operation for a couple of weeks, so far it worked flawlessly. With a small change in the XWISP2 configuration file, I was able to program the PIC14k50 as well. But of course, there is a big discalaimer, I only have a couple of PICs, so the solution is not tested extensivly, thus if you want a good and robust PIC programmer I advice you to buy or build the original WISP 648.</div><div><br /></div><div><span class="Apple-style-span" style="font-size: large;"><b>Conclusion</b></span></div><div>This small exerise shows the strenght(s) of JalV2 and Jallib, it shows how easy it is to port a large application from a PIC16f devices to a PIC18f device and that only a little effort is required to move from a RS-232 (UART) communcation interface to a USB (serial) based communication interface.</div><div><br /></div><div> </div><div><br /></div><div><br /></div><div><br /><br /><br /></div><div> </div>Alberthttp://www.blogger.com/profile/07474528874165692590noreply@blogger.com22tag:blogger.com,1999:blog-8299212346186005351.post-13992168763251540282009-08-02T11:17:00.009+02:002010-01-03T11:00:33.004+01:00Jaluino Medium 18F2550-based: first draft<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnEynucYJHZ3pPfZfg2JPEXd1y_l6by7PYbY9AKGThsREtVWDJHTX3ixj6hptzU8cmsuPw_Ar0H_H7zU3pK0RiAb9Xj9S4sx8EDDeXOkLyB-xEdDNzo-tCgNoUG83bJ0lR49mxq6sh8_c/s1600-h/ardui...err_jaluino_medium.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 265px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnEynucYJHZ3pPfZfg2JPEXd1y_l6by7PYbY9AKGThsREtVWDJHTX3ixj6hptzU8cmsuPw_Ar0H_H7zU3pK0RiAb9Xj9S4sx8EDDeXOkLyB-xEdDNzo-tCgNoUG83bJ0lR49mxq6sh8_c/s400/ardui...err_jaluino_medium.jpg" alt="" id="BLOGGER_PHOTO_ID_5365302866948509602" border="0" /></a><br /><br /><div style="text-align: center;"><span style="color: rgb(102, 0, 0); font-weight: bold;">Jaluino, with user guide, schematics, PCB, shields, etc... can now be reached on the following sites:</span><br /><br /><span style="font-weight: bold;">Main site</span>: <a href="http://jaluino.org/">http://jaluino.org</a><br /><span style="font-weight: bold;">Repository</span>: <a href="http://jaluino.googlecode.com/">http://jaluino.googlecode.com</a><br /><span style="font-weight: bold;">Group</span>: <a href="http://groups.google.com/group/jaluino">http://groups.google.com/group/jaluino</a><br /></div><br /><br /><br /><span style="color: rgb(153, 0, 0); font-style: italic;font-size:85%;" >Careful, schematic and PCB in this post aren't tested yet. Except if you're a daring risk-taker, you shouldn't build this board as it would only be a waste of time, and probably of money too... You've been warned.</span><br /><br />I'm still on this Jaluino board.<br /><br />While trying to get a working schematic, I've also spend a lot of time drawing the PCB. I focused on a <span style="font-weight: bold;">18F2550 version, instead of big fat 18F4550</span>, so <span style="font-weight: bold;">PCB layout is simpler</span> and I can focus more important issues for now. So this is now about <span style="font-weight: bold;">Jaluino Medium</span> (18F2550), not Jaluino Maxi (18F4550). BTW any ideas about "marketing" names to replace Mini, Medium and Maxi ?...<br /><br /><a href="http://jallib.blogspot.com/2009/07/jaluino-arduino-like-board-power-by-jal.html">Last schematic</a> contained lots of errors, mostly on USB and dual power. Luckily Guru Albert helped and provided me <a href="http://groups.google.com/group/jallib/msg/d73c1d64930e0b16?hl=en">four options</a>. I kept the simpler one (I can understand), which consists in having a jumper to select whether power should come from:<br /><ul><li> external supply (jack)</li><li>USB self-powered connector</li></ul><span style="font-style: italic;">(I would even add a new source of power: from serial, and more specifically from a USB-to-serial converter)</span><br /><br />The current schematic seems to look better (<span style="font-weight: bold; color: rgb(153, 0, 0);">yet still untested</span>, this will be for other posts).<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgc4joPaDB1-yiovaJhAWH7wQvKOReY0AWoVHPDTIKkgHnb4ab6PSZY74NcZ41gHlQ4CpGiSGa8x_vqOYBidMqSX3yEA4OKxc390TThCDPIYXmuMUBKSmj6PYtqGZurmFFTbgnGCIi8Tis/s1600-h/jaluino_sch3.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 185px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgc4joPaDB1-yiovaJhAWH7wQvKOReY0AWoVHPDTIKkgHnb4ab6PSZY74NcZ41gHlQ4CpGiSGa8x_vqOYBidMqSX3yEA4OKxc390TThCDPIYXmuMUBKSmj6PYtqGZurmFFTbgnGCIi8Tis/s400/jaluino_sch3.png" alt="" id="BLOGGER_PHOTO_ID_5365296622405556370" border="0" /></a><br /><br />So here how the PCB looks like now...<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqxp0qj4t0eqy2tRHcB5Zo3WRy-NLLv9pGfDhXUr9jcTkS81EBq4Tw2B9F3nF2pKi9eY9_UEyo8DaSbjubneNUAJEvmyePDTKcvnLn4HrneBOBaJeuV4wOpmc_yt-hxlHzhPNGan5VUQE/s1600-h/jaluino_pcb3.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 347px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqxp0qj4t0eqy2tRHcB5Zo3WRy-NLLv9pGfDhXUr9jcTkS81EBq4Tw2B9F3nF2pKi9eY9_UEyo8DaSbjubneNUAJEvmyePDTKcvnLn4HrneBOBaJeuV4wOpmc_yt-hxlHzhPNGan5VUQE/s400/jaluino_pcb3.png" alt="" id="BLOGGER_PHOTO_ID_5365296610843229746" border="0" /></a><br /><br />This PCB is expected to be 8.1cm x 7.1cm (3.2in x 2.81in). Compared to an original Arduino (6.9cm x 5.4cm), it's a little bit bigger. But it's also a single side board, and there are lots of other connectors (I²C and serial) not present in Arduino.<br /><br />There are several connectors. Some will be the shield connectors (JP1, JP2, JP4, JP5 and POWER), female headers as in Arduino, others (ICSP/JP6, I²C, serial) will be male headers.<br /><br />The shield is expected to be something like 4.8cm x 5.8cm (1.9in x 2.3in). Original Arduino's shield is 4.9cm x 4.3cm. It's a little bit bigger, and I may adjust connectors (move JP1 & JP2 lower) to have a "more squared shape".<br /><br /><br />Next posts will be about testing and prototyping this board, using a breadboard. This will also be a good exercise to have basic (and maybe advanced) experiments using jalv2 and jallib.<br /><br /><br /><span style="font-style: italic;">Sébastien Lelong</span>Sebastien Lelonghttp://www.blogger.com/profile/00317258446230687333noreply@blogger.com6tag:blogger.com,1999:blog-8299212346186005351.post-77556357046303973012009-07-30T20:44:00.017+02:002009-07-31T00:24:01.030+02:00PIC 18f14k50 USB Interface Board: Part 3<span style="font-size:180%;">Introduction</span><br />As promised, a blog about USB-HID devices. This blog will demonstrate how to create a USB-HID keyboard device running on the PIC 18f14k50 USB Interface Board. Making a HID device is a bit more complicated that getting the USB serial communication, becuase there are a wide range of HID devices, it is very hard to make a generic library. However, HID devices are nice, because you don't need a special drivers on the Host PC. There are many HID devices that can directly interact with the host operating systems, like keyboards, mice, joysticks etc, it is even possible to make a generic HID device, which can be controlled from a host application (but I will save that for another blog). Today were making a keyboard device, once you press the boot button it will generate a character. It is an educational example and does not have any practical use, but you can use it as a starting point to make for example a IR remote receiver that generate keystrokes.<br /><br />The Code<br />I've splitted up the code description in a couple of section, and it will explain it step by step. We start of with the regular stuff, not very existing and I won't explain it in more detail<br /><br /><span style="color:#330099;">-- chip setup</span><br /><span style="color:#330099;">include 18f14k50<br />pragma target clock 48_000_000</span><br /><span style="color:#330099;">include delay</span><br /><br />Before creating the USB descriptors, we need to include the USB constant definitions by<br /><br /><span style="color:#330099;">include usb_defs</span><br /><br />Ok, that was the easy stuff. USB works with enpoints, and we have to indicate which endpoints will be enabled, where there are located and specify their size, and endpoint can be considered more or less a communcation channel between the Host PC and the PIC device. An endpoint can consist of an input endpoint (seen from the Host computer, so output for the PIC device) and an output endpoints (again, seen from the Host computer, so input for the PIC device). An USB device should always have input & output enpoint zero, which is used for e.g. exchanging device configuration settings. In this example we will have and additional enpoint, which is used for the exchange of HID reports (i.e. the keyboard information). Furthermore, the an enpoint consist of two parts, the <strong>Endpoint Descriptor</strong> and the <strong>Enpoint Buffers</strong>, the setup of the <strong>Endpoint Descriptors</strong> are taken care of by the USB library, however, the <strong>Enpoint buffers</strong> have to be setup by the user of the library. The following code shows how to enable the endpoints and <strong>Endpoints Buffers</strong>:<br /><code><br /><span style="font-size:85%;"><span style="color:#330099;">const bit USB_EP0 = 1</span><br /><span style="color:#330099;">const byte USB_EP0_OUT_SIZE = 8</span><br /><span style="color:#330099;">const word USB_EP0_OUT_ADDR = ( USB_BASE_ADDRESS + 0x0010 )</span><br /><span style="color:#330099;">const byte USB_EP0_IN_SIZE = 8</span><br /></span><span style="font-size:85%;"><span style="color:#330099;">const word USB_EP0_IN_ADDR = ( USB_EP0_OUT_ADDR + USB_EP0_OUT_SIZE )<br /></span><br /><span style="color:#330099;">const bit USB_EP1 = 1</span><br /><span style="color:#330099;">const byte USB_EP1_OUT_SIZE = 8</span><br /><span style="color:#330099;">const word USB_EP1_OUT_ADDR = ( USB_EP0_IN_ADDR + USB_EP0_IN_SIZE )</span><br /><span style="color:#330099;">const byte USB_EP1_IN_SIZE = 8</span><br /></span><span style="font-size:85%;"><span style="color:#330099;">const word USB_EP1_IN_ADDR = ( USB_EP1_OUT_ADDR + USB_EP1_OUT_SIZE )<br /></span><br /><span style="color:#330099;">const bit USB_EP2 = 0</span><br /><span style="color:#330099;">const bit USB_EP3 = 0</span><br /><span style="color:#330099;"></span><br /><span style="color:#330099;">var volatile byte usb_ep1in_buf[ 8 ] at USB_EP1_IN_ADDR</span><br /><span style="color:#330099;"></span><br /></span></code><br />const bit USB_EPx = 1 indicates that the endpoint is enabled, if the endpoint is enabled the address of the <strong>Endpoint buffer</strong> must be specified, in addition, it should map within a special memory region. The USB hardware "talks" with the microcontroller via a dual access memory, this memory location is dependent on the PIC type, however its base addres <strong>USB_BASE_ADDRESS</strong> constant is defined usb_defs, so we can use this constant to setup the memory regions for the usb buffers independent of the PIC type. You might wonder why the enpoint buffers are not mapped at the beginning of the memory regions (<strong>USB_BASE_ADDRESS)</strong>, this is because the USB library needs to setup the <strong>Endpoint descriptors</strong>, they shall be located starting at the beginning of the dual access memory. To calculate the start of the memory region that can be used for the <strong>Endpoint buffers</strong>, take the highest enpoint number, add one, and multiply it by 8. So in this example we have endpoint 0 and 1, so 2 x 8 = 16 (0x10 hex).<br /><br />Well, that just beginning, next "record" we have to specify is the <strong>USB_DEVICE_DESCRIPTOR,</strong> it consists of 18 bytes and describes the device properties. Take a look at the usb specifiction (see <a href="http://www.usb.org/">http://www.usb.org/</a>) for the details.<br /><br /><br /><br /><pre class="source-code"><code><span style="font-size:85%;color:#000066;">const byte USB_DEVICE_DESCRIPTOR[USB_DEVICE_DESCRIPTOR_SIZE] = {<br /> USB_DEVICE_DESCRIPTOR_SIZE, -- 18 bytes long<br /> USB_DT_DEVICE, -- DEVICE 01h<br /> 0x00,<br /> 0x02, -- usb version 2.00<br /> 0x00, -- class<br /> 0x00, -- subclass<br /> 0x00, -- protocol<br /> USB_EP0_OUT_SIZE, -- max packet size for end point 0<br /> 0xd8,<br /> 0x04, -- Microchip's vendor<br /> 0x55,<br /> 0x00, -- Microchip keyboard demo<br /> 0x01,<br /> 0x00, -- version 1.0 of the product<br /> 0x01, -- string 1 for manufacturer<br /> 0x02, -- string 2 for product<br /> 0x00, -- string 3 for serial number<br /> 0x01 -- number of configurations<br />}<br /><br />const byte USB_STRING0[] =<br />{<br /> 0x04, -- bLength<br /> USB_DT_STRING, -- bDescriptorType<br /> 0x09, -- wLANGID[0] (low byte)<br /> 0x04 -- wLANGID[0] (high byte)<br />}<br /><br />const byte USB_STRING1[0x36] =<br />{<br /> 0x36, -- bLength<br /> USB_DT_STRING, -- bDescriptorType<br /> "M", 0x00,<br /> "i", 0x00,<br /> "c", 0x00,<br /> "r", 0x00,<br /> "o", 0x00,<br /> "c", 0x00,<br /> "h", 0x00,<br /> "i", 0x00,<br /> "p", 0x00,<br /> " ", 0x00,<br /> "T", 0x00,<br /> "e", 0x00,<br /> "c", 0x00,<br /> "h", 0x00,<br /> "n", 0x00,<br /> "o", 0x00,<br /> "l", 0x00,<br /> "o", 0x00,<br /> "g", 0x00,<br /> "y", 0x00,<br /> ",", 0x00,<br /> " ", 0x00,<br /> "I", 0x00,<br /> "n", 0x00,<br /> "c", 0x00,<br /> ".", 0x00<br />}<br /><br />const byte USB_STRING2[42] =<br />{<br /> 42, -- bLength<br /> USB_DT_STRING, -- bDescriptorType<br /> "J", 0x00,<br /> "A", 0x00,<br /> "L", 0x00,<br /> " ", 0x00,<br /> "H", 0x00,<br /> "I", 0x00,<br /> "D", 0x00,<br /> " ", 0x00,<br /> "K", 0x00,<br /> "e", 0x00,<br /> "b", 0x00,<br /> "o", 0x00,<br /> "a", 0x00,<br /> "r", 0x00,<br /> " ", 0x00,<br /> " ", 0x00,<br /> "D", 0x00,<br /> "e", 0x00,<br /> "m", 0x00,<br /> "o", 0x00<br />}<br /></span></code></pre><pre class="source-code"><code><span style="font-size:85%;color:#000066;"><br /></span></code> </pre><br />I'll not go into all the details of the USB descriptors, however, we need to specify USB_STRING0..3 because we filled in the USB string identifiers in the USB_DEVICE_DESCRIPTOR record. These string have to conform a predfined format, i.e. the first byte should specify the total record length, and the second byte indicates that it is a string USB_DT_STRING, furthermore, it has to be a unicode string, therefore after each character a 0x00 value needs to be defined. USB_String0 is a special string, since it specifies the language code, which is set to US English. Furthermore we specified there is one configuration record (last byte in the USB_DEVICE_DESCRIPTOR record.<br /><br />The <strong>USB_CONFIGURATION_DESCRIPTOR </strong>record specifies the properties of the USB device, again the details are available the USB specification at <a href="http://www.usb.org/">http://www.usb.org/</a>. High level description is that were setting up one configuration record for a HID device, which specifies the HID interface by pointing to the HID descriptor and it will have one endpoint (is number of enpoint exluding enpoint 0 which should always be present).<br /><br /><br /><br /><br /><br /></code><code><span style="font-size:85%;color:#000066;"><br /><br /><br /><br /></span></code><code><span style="font-size:85%;color:#000066;"><pre class="source-code"><code><br />const byte USB_HID_REPORT1[]=<br />{<br /> 0x05, 0x01, -- USAGE_PAGE (Generic Desktop)<br /> 0x09, 0x06, -- USAGE (Keyboard)<br /> 0xa1, 0x01, -- COLLECTION (Application)<br /> 0x05, 0x07, -- USAGE_PAGE (Keyboard)<br /> 0x19, 0xe0, -- USAGE_MINIMUM (Keyboard LeftControl)<br /> 0x29, 0xe7, -- USAGE_MAXIMUM (Keyboard Right GUI)<br /> 0x15, 0x00, -- LOGICAL_MINIMUM (0)<br /> 0x25, 0x01, -- LOGICAL_MAXIMUM (1)<br /> 0x75, 0x01, -- REPORT_SIZE (1)<br /> 0x95, 0x08, -- REPORT_COUNT (8)<br /> 0x81, 0x02, -- INPUT (Data,Var,Abs)<br /> 0x95, 0x01, -- REPORT_COUNT (1)<br /> 0x75, 0x08, -- REPORT_SIZE (8)<br /> 0x81, 0x03, -- INPUT (Cnst,Var,Abs)<br /> 0x95, 0x05, -- REPORT_COUNT (5)<br /> 0x75, 0x01, -- REPORT_SIZE (1)<br /> 0x05, 0x08, -- USAGE_PAGE (LEDs)<br /> 0x19, 0x01, -- USAGE_MINIMUM (Num Lock)<br /> 0x29, 0x05, -- USAGE_MAXIMUM (Kana)<br /> 0x91, 0x02, -- OUTPUT (Data,Var,Abs)<br /> 0x95, 0x01, -- REPORT_COUNT (1)<br /> 0x75, 0x03, -- REPORT_SIZE (3)<br /> 0x91, 0x03, -- OUTPUT (Cnst,Var,Abs)<br /> 0x95, 0x06, -- REPORT_COUNT (6)<br /> 0x75, 0x08, -- REPORT_SIZE (8)<br /> 0x15, 0x00, -- LOGICAL_MINIMUM (0)<br /> 0x25, 0x65, -- LOGICAL_MAXIMUM (101)<br /> 0x05, 0x07, -- USAGE_PAGE (Keyboard)<br /> 0x19, 0x00, -- USAGE_MINIMUM (Reserved (no event indicated))<br /> 0x29, 0x65, -- USAGE_MAXIMUM (Keyboard Application)<br /> 0x81, 0x00, -- INPUT (Data,Ary,Abs)<br /> 0xc0<br />}<br />const USB_CONFIGURATION_DESCRIPTOR_SIZE = 0x09 + 0x09 + 0x09 + 0x07<br /><br />const byte USB_CONFIGURATION_DESCRIPTOR[ USB_CONFIGURATION_DESCRIPTOR_SIZE ]=<br />{<br /> -- configuration descriptor - - - - - - - - - -<br /> 0x09, -- length,<br /> USB_DT_CONFIGURATION, -- descriptor_type<br /><br /> USB_CONFIGURATION_DESCRIPTOR_SIZE,<br /> 0x00, -- total_length;<br /><br /> 0x01, -- num_interfaces,<br /> 0x01, -- configuration_value,<br /> 0x00, -- configuration_string_id,<br /> 0b10000000, -- attributes (bus powered, no remote wake up)<br /> 100, -- max_power; (200ma)<br /><br /> -- interface descriptor - - - - - - - - - - - -<br /> 0x09, -- length,<br /> USB_DT_INTERFACE, -- descriptor_type,<br /> 0x00, -- interface_number, (starts at zero)<br /> 0x00, -- alternate_setting, (no alternatives)<br /> 0x01, -- num_endpoints,<br /> USB_HID_INTF, -- interface_class, (HID)<br /> USB_BOOT_INTF_SUBCLASS, -- interface_subclass, (boot)<br /> USB_HID_PROTOCOL_KEYBOARD, -- interface_protocol, (keyboard)<br /> 0x00, -- interface_string_id;<br /><br /> -- hid descriptor - - - - - - - - - - - - - - -<br /> 0x09, -- length,<br /> USB_DT_HID, -- descriptor_type;<br /> 0x11,<br /> 0x01, -- hid_spec in BCD (1.11)<br /> 0x00, -- country_code, (0=not country specific)<br /> 0x01, -- num_class_descriptors, (1)<br /> USB_DT_HID_REPORT, -- class_descriptor_type; (0x22 = report)<br /> (count( USB_HID_REPORT1 ) & 0xFF ),<br /> (count( USB_HID_REPORT1 ) >> 8 ),<br /><br /> 0x07, -- length,<br /> USB_DT_ENDPOINT, -- descriptor_type,<br /> 0b10000001, -- endpoint_address, (Endpoint 1, IN)<br /> USB_EPT_INT, -- attributes; (Interrupt)<br /> USB_EP1_IN_SIZE, <br /> 0x00, -- max_packet_size<br /> 0x01 -- interval (1ms)<br />}<br /><br /></code></pre><br /><br /><br /><br /><br /><br /></span></code><code><span style="font-size:85%;color:#000066;"></span></code><code><span style="font-size:85%;color:#000066;"></span></code><br /><br /><br />The <strong>HID Report</strong> specifies which information can be exchanged between the Host PC and the<br /></code>USB device. There are seperate specification available which describes the details of a HID report (again, see <a href="http://www.usb.org/">http://www.usb.org/</a>).<br />Making a HID report can be quite cumbersome, and there are even tools available to make HID report. Anyhow, for now assume that the specified HID report can exchange keyboard related information between the Host PC and the USB device<br /><br /><br />OK that was the toughest part, now some real JAL code.<br /><img class="gl_size" alt="Tekengrootte" src="http://www.blogger.com/img/blank.gif" border="0" /><br /><br /><br /><pre class="source-code"><code><span style="color:#330099;">-- include remaining USB libraries<br />include usb_drv_core<br />include usb_drv<br /><br />-- HID report layout (see USB specification for more details)<br />-- 0 Modifier byte<br />-- bit<br />-- 0 LEFT CTRL<br />-- 1 LEFT SHIFT<br />-- 2 LEFT ALT<br />-- 3 LEFT GUI<br />-- 4 RIGHT CTRL<br />-- 5 RIGHT SHIFT<br />-- 6 RIGHT ALT<br />-- 7 RIGHT GUI<br />-- 1 reserved<br />-- 2 keycode array (0)<br />-- 3 keycode array (1)<br />-- 4 keycode array (2)<br />-- 5 keycode array (3)<br />-- 6 keycode array (4)<br />-- 7 keycode array (5)<br />var byte hid_report_in[8] = { 0,0,0,0,0,0,0,0 }<br /><br />var byte key_value = 4<br />var bit sw3 is pin_c2<br />var bit latched_sw3 = sw3<br /><br /><br />-- disable analog unit, all ports set to digital<br />enable_digital_io()<br /><br />-- setup the USB device<br />usb_setup()<br /><br />-- enable USB device<br />usb_enable_module()<br /><br />-- set input where switch is attached to input<br />pin_c2_direction = input<br /><br />-- main loop<br />forever loop<br /> -- poll the usb ISR function on a regular base, in order to<br /> -- serve the USB requests<br /> usb_handle_isr()<br /> <br /> -- check if USB device has been configured by the HOST<br /> if usb_is_configured() then<br /><br /> -- prepare the HID buffer <br /> if ( sw3 != latched_sw3 ) then<br /><br /> latched_sw3 = sw3<br /> <br /> if ( sw3 == low )then<br /> hid_report_in[2] = key_value<br /> key_value = key_value + 1<br /> if ( key_value == 40 ) then<br /> key_value = 4<br /> end if<br /> else<br /> hid_report_in[2] = 0<br /> end if<br /> <br /> -- Send the 8 byte packet over USB to the host.<br /> usb_send_data(USB_HID_ENDPOINT, hid_report_in, count( hid_report_in ) , low )<br /><br /> -- debounce<br /> delay_1ms(50)<br /> end if<br /> end if<br />end loop</span><br /><br /></code></pre><br /><br /><br />First the remaing USB libraries have to be included, since the library need to have access<br />to the device and configuration records it has to be included after the definition of these recods. Next an array of 8 bytes is defined for the HID report were sending out from the device towards the HOST. The first byte is a modifier key, while the remaing bytes will contain the key character(s). More details can be found in the USB HID keyboard specification (see also <a href="http://www.usb.org/">www.usb.org</a>). Keep in mind though that the characters you send are not ASCII character, for example the "a" character has a byte value of 4.<br />Next the switch is initialized, and all inputs are set to digital io. Then the USB will be initialized by calling the usb_setup() and usb_enable_module() procedures. Then the main loop, first it has to call the usb_handle_isr() procedure on a regular base, in order to service the USB hardware. Next it will check if the USB interface is already configure by the host, via the usb_is_configured() function. If the USB device is recognized by the Host OS, it will check for state changes of the program switch of the PIC 18f14k50 USB Interface Board. If the value has changed and the button is pressed, it will send a HID report (i.e. it will send a character to the Host PC). The value of the character starts at 4 (the "a" character) and will increase till the "z" character, when reached it will start over again with the "a" character. It will fill in the character in the HID report and then it sends the HID report via USB towards the Host PC by calling the usb_send_data() procedure. Which will send the data via endpoint 1.<br /><br /><span style="font-size:180%;">Executing the demo</span><br />Compile the code (available at the Jallib SVN repository projects\pic14k50_usb_io\examples\blog_part3.jal) using the -loader18 flag. Reboot the PIC 18f14k50 USB Interface Board, while holding down the program and reset switch together and release the reset switch while keep holding down the program switch. After a couple of seconds you can release the program switch. Start the PDFSUSB.exe application to download the hex file. Once downloaded, press the reset button once again. After a couple of seconds the Host PC should recgonize the a new "Keyboard". Wait a couple of seconds, start an editor, for example notepad on the Host PC, if you now press & release the program button on the board, it should type a character within the editor, next time you press & release the program button it will show you the next character of the alphabet.<br /><br />OK, a long story this time, I know not everything has been explained in detail yet about the Jallib USB libraries, but maybe in a future blog I can tell more about the inner working of the Jallib USB libraries. The next episode will likely building a Generic HID device.Alberthttp://www.blogger.com/profile/07474528874165692590noreply@blogger.com10tag:blogger.com,1999:blog-8299212346186005351.post-32874157724080698142009-07-29T21:14:00.017+02:002009-08-06T23:23:15.644+02:00PIC 18f14k50 USB Interface Board: Part 4<div><span class="Apple-style-span" style="font-size:x-large;"><b>Introduction</b></span></div><div>This is a small follow up regarding the Jallib USB Serial library. Today's blog I'm showing how to make a more serious application with the PIC 18f14k50 USB Interface Board, namely a USB-RS-232 converter. I will go trough the source and explain the JAL code step by step.</div><div><br /></div><span class="Apple-style-span" style="font-size:large;"><span class="Apple-style-span" style="font-size:x-large;"><b>Source code</b></span><br /></span><div>The beginning is the same as Part 2, namely defining the target clockand including the device file.</div><div> </div><br /><pre style="font-family:arial;font-size:12px;border:1px dashed #CCCCCC;width:99%;height:auto;overflow:auto;background:#f0f0f0;;background-image:URL(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOzPi26QZxIGlThA5M4Mqu0ETqTZb3De654JsGPsRTvAqh2somUTNT5G7M7TvhbxaJqf-FcKY0IfvHqLDcWYSqLwfYNmaAQSco3O4jbjIHc0RK71mMzZY_gsL90kkkR-0etX0oJLm2wdv7/s320/codebg.gif);padding:0px;color:#000000;text-align:left;line-height:20px;"><code style="color:#000000;word-wrap:normal;">1: -- chip setup<br />2: include 18f14k50<br />3:<br />4: -- even though the external crystal is 20 MHz, the configuration is such that<br />5: -- the CPU clock is derived from the 96 Mhz PLL clock (div2), therefore set<br />6: -- target frequency to 48 MHz<br />7: pragma target clock 48_000_000<br />8:<br /></code></pre><div><br /></div><div><span class="Apple-style-span" style="font-size:x-large;"><b>Serial interrupt handling</b></span></div><div><span class="Apple-style-span" style="font-size:180%;"><span class="Apple-style-span" style="font-size:18px;"><span class="Apple-style-span" style=" ;font-size:16px;"><div>Then we need to declare a forward procedure in order to receive the line setting change events, which will be discussed a bit later on. In addition the usb_serial library has to be included as well as the print library so for now we have to add the following code (line 1-7)</div><div><br /></div></span></span></span></div><pre style="font-family:arial;font-size:12px;border:1px dashed #CCCCCC;width:99%;height:auto;overflow:auto;background:#f0f0f0;;background-image:URL(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOzPi26QZxIGlThA5M4Mqu0ETqTZb3De654JsGPsRTvAqh2somUTNT5G7M7TvhbxaJqf-FcKY0IfvHqLDcWYSqLwfYNmaAQSco3O4jbjIHc0RK71mMzZY_gsL90kkkR-0etX0oJLm2wdv7/s320/codebg.gif);padding:0px;color:#000000;text-align:left;line-height:20px;"><code style="color:#000000;word-wrap:normal;">1: -- forward procedure declaration<br />2: procedure usb_cdc_line_coding_changed_callback()<br />3:<br />4: -- include standard libraries<br />5: include delay<br />6: include usb_serial<br />7: include print<br />8:<br />9: procedure _serial_receive_interrupt_handler() is<br />10: pragma interrupt<br />11: <br />12: <br />13: if (PIR1_RCIF == TRUE) then -- UART receive interrupt<br />14:<br />15: if ((RCSTA_OERR == TRUE) | (RCSTA_FERR == TRUE)) then -- frame/overr error<br />16: var byte x = RCREG -- flush hardware buffer<br />17: while RCSTA_OERR == TRUE loop -- overrun state<br />18: RCSTA_CREN = FALSE -- disable UART<br />19: RCSTA_CREN = TRUE -- re-enable UART<br />20: x = RCREG -- \ flush hardware buffers<br />21: x = RCREG -- /<br />22: end loop -- until no more overrun<br />23:<br />24: else -- data without errors<br />25: var byte ch = RCREG<br />26: -- usb_serial_data = RCREG<br />27: usb_cdc_putc( ch )<br />28: end if<br />29: end if<br />30: end procedure<br />31:<br />32:<br /></code></pre><div>From line 9-30, the interrupt routine to handle the receiving of the UART characters. As discussed in the previous blog, the USB library is not interrupt driven, therefore the USB service procedure must be called on a regular base to service the USB hardware. Servicing can be time consuming therefore I've decided to make the RS-232 serial interface (UART) interrupt driven, so were sure that were not lossing incoming data on the UART. The incoming data will be placed directly in the USB transmit ring buffer by calling the usb_cdc_putc( ch ) procedure. The USB-Serial serving procedure checks if there is data present in the ring buffer.</div><div><br /></div><div><div><span class="Apple-style-span" style="font-size:180%;"><span class="Apple-style-span" style="font-size:18px;"><br /></span></span></div><div><span class="Apple-style-span" style="font-size:x-large;"><b>Handling baudrate settings</b></span></div></div><div>Next code section is the handling of the baudrate settings. The USB serial library has a callback function usb_cdc_line_coding_changed_callback() , when defined, it will be called each time the USB Host will request the line coding setting (which contains the baudrate, parity, stopbits etc). The procedure entry is on line 45 in the code below, the procedure checks/limits the baudrate settings and will change the baudrate (line 2-23) and by re-initializing the UART hardware (line 27-42).</div><div> </div><br /><pre style="font-family:arial;font-size:12px;border:1px dashed #CCCCCC;width:99%;height:auto;overflow:auto;background:#f0f0f0;;background-image:URL(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOzPi26QZxIGlThA5M4Mqu0ETqTZb3De654JsGPsRTvAqh2somUTNT5G7M7TvhbxaJqf-FcKY0IfvHqLDcWYSqLwfYNmaAQSco3O4jbjIHc0RK71mMzZY_gsL90kkkR-0etX0oJLm2wdv7/s320/codebg.gif);padding:0px;color:#000000;text-align:left;line-height:20px;"><code style="color:#000000;word-wrap:normal;">1: -- procedure to change the baudrate settings of the UART<br />2: procedure change_baudrate( dword in baud_rate) is <br />3: <br />4: -- compiler issue with -const-detect<br />5: if true then<br />6: var dword fosc_div4 = dword( target_clock ) / 4<br />7: else<br />8: var dword fosc_div4<br />9: fosc_div4 = dword( target_clock )<br />10: fosc_div4 = fosc_div4 / 4 <br />11: end if<br />12: <br />13: var dword div_factor = fosc_div4 / baud_rate - 1<br />14: var word div_wfactor = word( div_factor )<br />15: var byte div_btfactor[2] at div_wfactor<br />16: <br />17: TXSTA_BRGH = true<br />18: BAUDCON_BRG16 = true<br />19: <br />20: SPBRGH = div_btfactor[1]<br />21: SPBRG = div_btfactor[0]<br />22: <br />23: end procedure<br />24: <br />25: <br />26: -- Initializes the serial port, calculates baudrate registers.<br />27: procedure serial_hw_init() is<br />28: RCSTA = 0b0000_0000 -- reset<br />29: RCSTA_SPEN = enabled -- serial port enable<br />30: RCSTA_CREN = enabled -- continuous receive enable<br />31: <br />32: TXSTA = 0b0000_0100 -- reset (16 bit, asyn)<br />33: TXSTA_TXEN = enabled -- UART transmit enabled<br />34: -- TXSTA_SYNC = true<br />35: TXSTA_BRGH = true<br />36: BAUDCON_BRG16 = true<br />37: <br />38: PIE1_RCIE = enabled -- UART receive int. enable<br />39: -- (PIE1_TXIE dynamically)<br />40: INTCON_PEIE = enabled -- periferal<br />41: INTCON_GIE = enabled -- general<br />42: end procedure<br />43: <br />44: -- callback procedure, is called if the USB Host changes the line settings<br />45: procedure usb_cdc_line_coding_changed_callback() is<br />46: <br />47: if ( cdc_line_coding_dte_rate > 115200 ) then<br />48: cdc_line_coding_dte_rate = 115200<br />49: end if<br />50: change_baudrate( cdc_line_coding_dte_rate )<br />51: serial_hw_init()<br />52: end procedure<br />53: <br /></code></pre><div><br /></div><div><span class="Apple-style-span" style="font-size:x-large;"><b>The main loop</b></span></div><div>Finally we need to initalize the hardware and define the main loop. First all IO ports are set to digital (line 3) and need to initialize the USB serial library (line 6). Next a character is defined which holds the receiving character.</div><br /><pre style="font-family:arial;font-size:12px;border:1px dashed #CCCCCC;width:99%;height:auto;overflow:auto;background:#f0f0f0;;background-image:URL(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOzPi26QZxIGlThA5M4Mqu0ETqTZb3De654JsGPsRTvAqh2somUTNT5G7M7TvhbxaJqf-FcKY0IfvHqLDcWYSqLwfYNmaAQSco3O4jbjIHc0RK71mMzZY_gsL90kkkR-0etX0oJLm2wdv7/s320/codebg.gif);padding:0px;color:#000000;text-align:left;line-height:20px;"><code style="color:#000000;word-wrap:normal;">1: <br />2: -- disable analog<br />3: enable_digital_io()<br />4: <br />5: -- setup the USB serial library<br />6: usb_serial_init()<br />7: <br />8: var byte ch<br />9: <br />10: -- main loop<br />11: forever loop<br />12: -- poll the usb ISR function on a regular base, in order to <br />13: -- serve the USB requests<br />14: usb_serial_flush()<br />15: <br />16: -- check if USB device has been configured by the HOST<br />17: if ( usb_cdc_line_status() != 0x00 ) then<br />18: <br />19: -- check for input character<br />20: while usb_serial_read( ch ) loop<br />21: -- echo input character<br />22: TXREG = ch <br />23: while ! PIR1_TXIF loop end loop<br />24: end loop<br />25: <br />26: end if<br />27: end loop<br /></code></pre>Finally the main loop, as said before, the usb_serial_flush() procedure has to be called on a regular base. This function takes care of transmitting the character to the USB Host that have been received by the UART, and it also takes care of putting the character that are sent from USB Host into a receive buffer. <div><br /><div>A rough calculation on the maximum interval time between two USB Serial flush:<div>By default the USB-Serial library will create a ring buffer of 32 bytes, which is for this application more than sufficient (max UART speed is ~10.000 characters/second, so USB Serial flush must be called at least every 10.000 / 32 = 3.2 ms. So there is enough time left to perform additional taks<div></div></div><div><br /></div><div>On line 17 it checks if the USB Host is connected, if so, it will put all character that were sent by the USB Host in the UART Transmit register (line 19-24).</div><div><br /></div><div>That's about it, this blog showed how to create a simple USB-RS-232 convert, using the JALLB USB serial librray and the PIC 18f14k50 USB Interface Board. Possible extentions are to include RS-232 handshaking and to take other RS-232 line setting into account.</div><div><br /></div><div> </div><div><br /></div><div><div><div><br /><div></div></div></div></div></div></div>Alberthttp://www.blogger.com/profile/07474528874165692590noreply@blogger.com0tag:blogger.com,1999:blog-8299212346186005351.post-68465065015987241222009-07-26T00:07:00.016+02:002009-07-31T00:28:34.600+02:00PIC 18f14k50 USB Interface Board: Part 2This is the second episode about the PIC 18f14k50 USB Interface Board. This time I want to take about the usage of the JALLIB USB-Serial library and how it can be used in conjuction with the interface board.<br /><br /><span style="font-size:180%;"><strong>Introduction </strong><br /></span>USB is a fairly complex interface, besides the basic interface, there are defined a couple of higher level "protocols" which are target for specific "device" functions. Commonly used interfaces are the Human Interface Device(s) types, to support devices like keyboards, joysticks and other devices, another commenly used interace is the Communication Device Class (CDC), which is developped for a broad range of (serial) communication devices, like modems, RS-232 converters etc. HID devices will be discussed in another blog, today we're looking a bit closer on the CDC interface and how to talk to the PIC device with a terminal application via the USB interface.<br /><br />In order to reduce the USB learning curve, we've devevlopped a special library (USB-Serial) to easily create firmware that behaves like a RS-232 port on the Host side (virtual COM port). The big advantage is that you can still use the good old terminal application(s) to talk with your PIC device via the USB interface (both on Windows and Linux and probably other Host operating systems)<br /><br />As an example we use the 18f14k50_board_test.jal, we start of simple and show step by step how to use the usb_serial library.<br /><br /><span style="font-size:130%;"><strong>USB Serial example code</strong></span><br />We start of with a basic application, the code is listed below:<br /><br /><pre class="source-code"><code><span style="color:#330099;"><span style="font-size:85%;">include 18f14k50 -- target PICmicro<br /><br />--<br />-- This program assumes a 12 MHz resonator or crystal<br />-- is connected to pins OSC1 and OSC2.<br />-- Configuration bits may cause a different frequency!<br />pragma target clock 48_000_000 -- oscillator frequency<br /><br />-- include libraries<br />include usb_serial<br />include print<br /><br />-- initialize the USB serial library<br />usb_serial_init()<br /><br /><br />-- main loop<br />forever loop<br /> <br /> var byte ch<br /><br /> -- Service USB, call on a regular base to keep communcaiton going<br /> usb_serial_flush()<br /><br /> -- check for input character<br /> if usb_serial_read( ch ) then<br /> -- nothing spectecular, echo ch + 1<br /> if ch == "?" then<br /> const byte str1[] = "Hi there \r\n"<br /> print_string( usb_serial_data, str1 )<br /> else<br /> usb_serial_data = ch<br /> end if<br /> end if<br />end loop<br />--</span></span><br /><br /></code></pre><br /><br />The code is pretty straight forward, first the device file is included and the target clock speed is set. Then the usb_serial and print JALLIB libraries are included. The next step is to initalize the USB serial library by calling the usb_serial_init() procedure. Within the main loop, the usb_serial_flush() is called, so the USB serial Interface Enginge (SIE) is serviced on a regular base (the USB libraries are not interrupt driven, therefore this procedure must be called regulary.<br />The call towards usb_serial_read will check if there are character recieved from the USB Host, if a character has been received it will be echoed, unless the "?" character is send, then it will use print the "Hi there" string. Notice that the usb_serial library can be used in conjuction with the print and serial libraries, if the usb_serial_data argument is passed along (as the first argument) with the print related procedure calls.<br /><br /><strong><span style="font-size:180%;">Get it running</span><br /></strong>The code is compiled with jalv2 using the -loader18 -no-fuse. After compilation one can reset the PIC 18f14k50 USB Interface Board and holding down the program button. Now the PDFSUSB application can be used to download the HEX file file, after download reset the board. If everything went OK, it should recognize the USB-CDC device and ask for drivers (Windows only), select the driver (which can be downloaded from<br /><a href="http://groups.google.com/group/jallib/files">http://groups.google.com/group/jallib/files</a>, file usb_cdc_drivers.zip), by selecting the win2k_xp_vista32_64 directory. After installtion of the drivers, the host operating system will create a new (virtual) serial port.<br />After the (virtual) serial port is created, open the serial port with your favorite terminal appliction. The actual serial port settings does not really matter, once the serial port is opened, you can any send character, the character will be echoed unless the "?" mark character is sent, the it will respond by the "Hi There" sentence.<br /><br /><span style="font-size:130%;"><strong>Wrap Up</strong></span><br />So far about the usb_serial library, it shows how easy it is to create an PIC firmware application using which can comminicate with a Host PC via the USB interface. Upcoming blog will address more advanced usage of the USB interface by creating a HID device,.Alberthttp://www.blogger.com/profile/07474528874165692590noreply@blogger.com7tag:blogger.com,1999:blog-8299212346186005351.post-41469929764721427432009-07-23T17:52:00.023+02:002010-01-03T11:00:44.135+01:00Jaluino: an Arduino-like board, power by jal<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglRwYE8oq3wCzs_jND5AwUeR1mc1ZLxSbEEErNk7IRbMwtQ5r8taVu2ImTZ2J9igx3xX_uNxTmEJN_2r2CdY0hJ6s-OGK938G_McB9KJ0yOpd-RVXVcRevANfAKLQzE4HmoAVSiJKJbtY/s1600-h/ardui...err_jaluino.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 265px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglRwYE8oq3wCzs_jND5AwUeR1mc1ZLxSbEEErNk7IRbMwtQ5r8taVu2ImTZ2J9igx3xX_uNxTmEJN_2r2CdY0hJ6s-OGK938G_McB9KJ0yOpd-RVXVcRevANfAKLQzE4HmoAVSiJKJbtY/s400/ardui...err_jaluino.jpg" alt="" id="BLOGGER_PHOTO_ID_5361700884083488690" border="0" /></a><br /><div style="text-align: center;"><span style="color: rgb(102, 0, 0); font-weight: bold;">Jaluino, with user guide, schematics, PCB, shields, etc... can now be reached on the following sites:</span><br /><br /><span style="font-weight: bold;">Main site</span>: <a href="http://jaluino.org/">http://jaluino.org</a><br /><span style="font-weight: bold;">Repository</span>: <a href="http://jaluino.googlecode.com/">http://jaluino.googlecode.com</a><br /><span style="font-weight: bold;">Group</span>: <a href="http://groups.google.com/group/jaluino">http://groups.google.com/group/jaluino</a><br /></div><br /><br />It's been a while I'd like to build and provide the same kind of board as Arduino's, but <span style="font-weight: bold;">PIC-based</span>. And powered by <span style="font-weight: bold;">Jalv2 and jallib</span>, of course. The reasons are pretty clear: as we share our jal code (software), why don't we also share our boards & PCB (hardware) ? <span style="font-weight: bold;">Jaluino </span>to the rescue !<br /><br />There can be many benefits having such a board, such a common hardware. For instance, everybody would be able to get a board, and experiment with it (educational benefits). Keeping hardware problems away helps focusing on the real experiment's content. Jaluino provides a base, a context on which anyone can build extra boards. These can then be shared with everyone, easily, since Jaluino is the common base. This is what Arduino's shields are about, and what would be nice to reproduce.<br /><br /><br /><span style="font-size:130%;"><span style="font-weight: bold;">Which PIC should be used for Jaluino ?</span></span><br /><br />The size and the features are what matter. A <span style="font-weight: bold;">USB capable PIC</span> is somewhat mandatory, it opens oportunities for nice experimentation. 18F PICs seem to be the candidates. What about these three PICs:<br /><br /><ul><li><span style="font-weight: bold;">18F14K50 </span>: 20-pin, cheap, lots of features</li><li><span style="font-weight: bold;">18F2550 </span>: 28-pin</li><li><span style="font-weight: bold;">18F4550 </span>: big fat 40-pin, the max for a PDIP package.<br /></li></ul>Following Arduino's ideas, several Jaluino boards could be provided:<br /><br /><ul><li><span style="font-weight: bold;">Jaluino Mini</span> : 18F14K50 based, breadboard layout (no shield connectors, just plug your Jaluino board on a breadboard). Closed to <a href="http://jpmandon.blogspot.com/">Pinguino</a>, but with a smaller PIC</li><li><span style="font-weight: bold;">Jaluino Medium</span> : 18F2550 based. Board contains connectors on which we can plug shields. A breadboard version can also be built (same as Pinguino)</li><li><span style="font-weight: bold;">Jaluino Maxi</span> : 18F4550 based. Board is "shieldable" too, a breadboard version may not be a good idea, as the PIC is quite big a would require a rather large breadboard.<br /></li></ul><br />(we'd definitively need to work on marketing names for "<span style="font-style: italic;">Mini</span>", "<span style="font-style: italic;">Medium</span>", "<span style="font-style: italic;">Maxi</span>"...)<br /><br /><br /><span style="font-size:130%;"> <span style="font-weight: bold;">Connectors for shields</span></span><br /><br />Despite several Jaluino boards would be available, shield connectors have to be compatible. Ex: a shield for 18F2550 can be used with a 18F4550 (the reverse isn't true...). As Arduino Diecilima's shields are compatible with Arduino Mega. This can be done by extanding the 18F2550 layout by other connectors.<br /><br />Comparing 18F2550 and 18F4550 pins, we can see one is perfectly included into the other. In green, pins from 18F2550 which be found in 18F4550, in blue, 18F4550 only pins. Circle-red pins are important features: <span style="font-style: italic;">serial</span>, <span style="font-style: italic;">I²C</span>, <span style="font-style: italic;">USB </span>and <span style="font-style: italic;">OSC</span>. Fortunatly, these are carried by the exact same pins between 18F2550 and 18F4550.<br /><br /><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhg1ponP7yZ-xkP3Knbg3RrjF-HnUi8dhH085QehVtKJbJ4m0raa-OLPrskNl171vTs1UEInQvCaNLllcTKFXnpfGMxLYWUVyNlTdp0uEbkFfVhPqcs68nIGv4m9AHzYKSbelglgV9YS90/s1600-h/18F2550.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 180px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhg1ponP7yZ-xkP3Knbg3RrjF-HnUi8dhH085QehVtKJbJ4m0raa-OLPrskNl171vTs1UEInQvCaNLllcTKFXnpfGMxLYWUVyNlTdp0uEbkFfVhPqcs68nIGv4m9AHzYKSbelglgV9YS90/s400/18F2550.png" alt="" id="BLOGGER_PHOTO_ID_5361696795273830514" border="0" /></a><span style="font-weight: bold; font-style: italic;">PIC 18F2550</span><br /><br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpW3Hr6L7mh7Ke7Ud26nvokJXOmDBHoFgmOPTiTeV8A-1qUw8FG-kTjRLTs712Zga5hjH4tIjXR_uRasXQgBa7hH3_oXc9tNInvmQYC9W9AhElWydvwXZ3CzPLaGlPIfPlf0-42tv0x80/s1600-h/18F4550.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 235px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpW3Hr6L7mh7Ke7Ud26nvokJXOmDBHoFgmOPTiTeV8A-1qUw8FG-kTjRLTs712Zga5hjH4tIjXR_uRasXQgBa7hH3_oXc9tNInvmQYC9W9AhElWydvwXZ3CzPLaGlPIfPlf0-42tv0x80/s400/18F4550.png" alt="" id="BLOGGER_PHOTO_ID_5361696799283910594" border="0" /></a><span style="font-weight: bold; font-style: italic;">PIC 18F4550</span><br /></div><br /><span style="font-style: italic;">(also note 18F877 could be used and plugged into a Jaluino Maxi as OSC, RX/TX are carried by the same pins as in 18F4550. Only I²C </span><span style="font-style: italic;">-- and USB of course -- pins aren't compatible).</span><br /><br />The general layout for Jaluino Medium and Jaluino Maxi would look like this (not scaled...). Orange connector is dedicated to power supply. Green connectors are exactly on the place between Maxi and Medium Layout, these are the compatible pins. Blue connectors export 18F4550 pins only.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaMptHC8qfGmvBDDpZK4qaFIP-pKvoMXQ8YvuHjsu3PFU3J0zVpUAZWQLwA3mbmW3RVk-UtnhlengAeovJIRLrZ2GUj45l0Nmkv3Os-KyWYHKMSTIa56jTRw3CpZYARZpKASbnS5GGiV0/s1600-h/medium.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 392px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaMptHC8qfGmvBDDpZK4qaFIP-pKvoMXQ8YvuHjsu3PFU3J0zVpUAZWQLwA3mbmW3RVk-UtnhlengAeovJIRLrZ2GUj45l0Nmkv3Os-KyWYHKMSTIa56jTRw3CpZYARZpKASbnS5GGiV0/s400/medium.jpg" alt="" id="BLOGGER_PHOTO_ID_5361698753775790018" border="0" /></a><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBrt7n_2pvac-WcDW_ZvmZ4YoUt9TK-KmNxRsf5BlzSX8GJtQd9i4vXFJE5OfspitZOqPgyIPWjXXUVGFv5Pk5CT1FWP_XvnEterTLfVLoxROUK-VqHdO3X-VvhaRyPwt08f2LomiR31Q/s1600-h/maxi.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 355px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBrt7n_2pvac-WcDW_ZvmZ4YoUt9TK-KmNxRsf5BlzSX8GJtQd9i4vXFJE5OfspitZOqPgyIPWjXXUVGFv5Pk5CT1FWP_XvnEterTLfVLoxROUK-VqHdO3X-VvhaRyPwt08f2LomiR31Q/s400/maxi.jpg" alt="" id="BLOGGER_PHOTO_ID_5361697629278574898" border="0" /></a><br /><span style="font-size:130%;"> <span style="font-weight: bold;">Other connectors...</span></span><br /><br />Several other connectors would be needed:<br /><br /><ul><li>USB, of course...<br /></li><li>I²C : following <a href="http://groups.google.com/group/jallib/msg/2042aeffaba02b33?hl=en">Joep's suggestion</a>, a 5-pin header (+9V,+5V, GND, SCL, SDA) can be used a dedicated connector, making easier connection between boards & other parts using this protocol</li><li>Serial : again, following <a href="http://groups.google.com/group/jallib/msg/2042aeffaba02b33?hl=en">Joep's suggestion</a>, a 4-pin header (+5V, GND, TX, RX) would allow to plug any serial module (see later)<br /></li><li>ICSP : to easily program the chip, even if no bootloader is present</li></ul><br /><span style="font-size:130%;"> <span style="font-weight: bold;">Serial : different options<br /></span></span><br />In addition to dedicated USB connector, a serial connector would allow easy comms. from Jaluino to the external world. But what type of connector to provide ? DB9 ? USB via USB-to-serial conversion ?<br /><br />Here are the different alternatives, depending on budget limits, easiness to make, and parts used to build this module:<br /><br /><ul><li><span style="font-weight: bold;">USB-to-Serial via FDTI chip</span>: widely parts, but FTDI chip only exist on SSOP package, hard to solder (but not impossible). Small. USB can be used to power the board.<br /></li><li><span style="font-weight: bold;">USB-to-Serial, using a 18F14K50</span> : easy to make (though 18F14K50 may be quite hard to find...). Size to define. USB can be used to power the board.<br /></li><li><span style="font-weight: bold;">DB9 connector, using MAX232 chip</span> : classical, quite big. External power supply will be required</li><li><span style="font-weight: bold;">what-you-want option</span>: just plug a module which honor the connector's interface. For instance, I have a bluetooth-to-serial module, this gives the opportunity to easily integrate it to Jaluino.<br /></li></ul><br /><span style="font-size:130%;"><span style="font-weight: bold;">Few words about bootloader</span></span><br /><span style="font-size:130%;"><span style="font-weight: bold;"><br /></span></span>ICSP connector make the develop-program-test cycle faster, preventing unplug/plug the chip to program it. But still it requires a programmer... A bootloader is required here.<br /><br />There are many different ones out there, but <a href="http://www.etc.ugal.ro/cchiculita/software/picbootloader.htm">Tiny Bootloader</a> is widely used, very (very) small, many different programs exits for many different platforms. Bootloader should be able to be triggered without having to manually reset the device (see <a href="http://www.etc.ugal.ro/cchiculita/software/tinybldusage.htm">here</a> for more, it seems to require some hardware parts).<br /><br /><br /><span style="font-size:130%;"> <span style="font-weight: bold;">A first schematic</span></span><br /><br />I started to build a schematic. Please keep in mind this is very alpha, and this is not even supposed to work...<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjC1H2mc1g70zofV-HCOqYS1S4swh8YWMyFm_AJ_PdiqxPhGzRahyphenhypheniHk-Qfm5YxZm2zMlkFGHUJEAQYJTHjiJ2TPc4IRHcDc3nGN4bLZ6uNNEBaDwaxZS0F_L7-ysWchKvQWB4OvC0I_pU/s1600-h/jaluino_sch2.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 192px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjC1H2mc1g70zofV-HCOqYS1S4swh8YWMyFm_AJ_PdiqxPhGzRahyphenhypheniHk-Qfm5YxZm2zMlkFGHUJEAQYJTHjiJ2TPc4IRHcDc3nGN4bLZ6uNNEBaDwaxZS0F_L7-ysWchKvQWB4OvC0I_pU/s400/jaluino_sch2.png" alt="" id="BLOGGER_PHOTO_ID_5361723476042259042" border="0" /></a><br /><br /><br /><span style="font-weight: bold;font-size:130%;" >License</span><br /><br />Following Arduino, I'd like to release Jaluino schematics & PCB under <span style="font-weight: bold;">Creative Commons Attribution-Share Alike 3.0</span>.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrDGyw009cIe5-MHMCEkPxIfGkVze_GZa76GVDKJyKBbHNEOsI_XdN4WOE_g5E9wfITFWLRNV7UdxOQkxgnGya_-kpYQSEKNsfG55byUJlKGCl8udwZELwYpHhyphenhyphendEB5WBhhPoVrLU82LI/s1600-h/ccbysa.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 88px; height: 31px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrDGyw009cIe5-MHMCEkPxIfGkVze_GZa76GVDKJyKBbHNEOsI_XdN4WOE_g5E9wfITFWLRNV7UdxOQkxgnGya_-kpYQSEKNsfG55byUJlKGCl8udwZELwYpHhyphenhyphendEB5WBhhPoVrLU82LI/s400/ccbysa.png" alt="" id="BLOGGER_PHOTO_ID_5361717822828043730" border="0" /></a><br />Basically, it says:<br /><br /><ul><li><strong>Attribution</strong> — <span id="attribution-container">You must attribute the work in the manner specified by the author or licensor (but not in any way that suggests that they endorse you or your use of the work).</span></li><li><strong>Share Alike</strong> — <span>If you alter, transform, or build upon this work, you may distribute the resulting work only under the same, similar or a compatible license.</span></li></ul> See <a href="http://creativecommons.org/licenses/by-sa/3.0/">here</a> for more details.<br /><br /><br />Any suggestions ? Would you like to join the effort ?<br /><br /><br />PS: see <a href="http://groups.google.com/group/jallib/topics?hl=en&start=20&sa=N">this thread</a> on jallib group for a discussion. Also <a href="http://groups.google.com/group/jallib/search?hl=en&group=jallib&q=jaluino&qt_g=Search+this+group">search</a> the group more...<br /><br /><br /><br /><span style="font-style: italic;">Sébastien Lelong</span>Sebastien Lelonghttp://www.blogger.com/profile/00317258446230687333noreply@blogger.com6tag:blogger.com,1999:blog-8299212346186005351.post-47874796964080555142009-07-10T19:32:00.020+02:002009-07-19T11:06:18.170+02:00Using new ADC librariesSince several weeks or months, quite a lot of effort has been put into the development and update of ADC libraries. Why ? Because when Guru Stef Mientki first developed this library, he designed it for quite a few PICs (but most used ones at this time). Since jallib is to support all (or as much as) possible PICs, it was time to have a look on this huge piece of code...<br /><span style="font-size:130%;"><br /><br /></span><span style="font-weight: bold;font-size:130%;" >Many different cases...</span><span style="font-size:130%;"> </span><br /><br />As usual, Microchip PICs offers a wide choice configuring ADC: <ul style="font-size:12px;"><li style="font-size:12px;"><span style="font-weight: bold;font-size:100%;" >Not all PICs</span><span style="font-size:100%;"> have ADC module (...) </span></li><li style="font-size:12px;"><span style="font-size:100%;">Analog pins are </span><span style="font-weight: bold;font-size:100%;" >dispatched</span><span style="font-weight: bold;font-size:100%;" > differently</span><span style="font-size:100%;"> amongst PICs, still for user's sake, they have to be automatically configured as input. We thus need to know, for each PIC, where analog pins are...</span></li><li style="font-size:12px;"><span style="font-size:100%;">Some PICs have their </span><span style="font-weight: bold;font-size:100%;" >analog pins dependent</span><span style="font-size:100%;"> from each other, and some are </span><span style="font-weight: bold;font-size:100%;" >independent</span><span style="font-size:100%;"> (more on this later)</span></li><li style="font-size:12px;"><span style="font-weight: bold;font-size:100%;" >Clock configuration</span><span style="font-size:100%;"> can be different</span></li><li style="font-size:12px;"><span style="font-size:100%;">Some PICs have </span><span style="font-weight: bold;font-size:100%;" >8-bits low resolution</span><span style="font-size:100%;"> ADC module, some have </span><span style="font-weight: bold;font-size:100%;" >10-bits high resolution</span><span style="font-size:100%;"> ADC module (and some have 12-bits, those aren't currently handled, that's a restriction...) </span></li><li style="font-size:12px;"><span style="font-size:100%;">Some PICs can have </span><span style="font-weight: bold;font-size:100%;" >two voltage references</span><span style="font-size:100%;"> (VRef+ and VRef-), only </span><span style="font-weight: bold;font-size:100%;" >one voltage reference</span><span style="font-size:100%;"> (Vref+) and some </span><span style="font-weight: bold;font-size:100%;" >can't handle voltage references</span><span style="font-size:100%;"> at all</span></li><li style="font-size:12px;"><span style="font-size:100%;">(and probably other differences I can't remember :)...</span> </li></ul> Luckily most of these differences are transparent to users (hey, that was the goal of this refactoring/rewriting...). <span style="font-size:100%;"><br /><br /><br /></span><span style="font-weight: bold;font-size:130%;" >Dependent and independent analog pins</span><br /><br /><span style="font-size:100%;"> OK, let's write some code ! But before this, you have to understand one very important point: some PICs have their analog pins </span><span style="font-style: italic;font-size:100%;" >dependent</span><span style="font-size:100%;"> from each other, some PICs have their analog pins </span><span style="font-style: italic;font-size:100%;" >independent</span><span style="font-size:100%;"> from each other. "</span><span style="font-style: italic;font-size:100%;" >What is this suppose to mean ?</span><span style="font-size:100%;">" I can hear... Let's consider two famous PICs: 16F877 and 16F88. 16F877 datasheet explains how to configure the number of analog pins, and vref, setting </span><span style="font-weight: bold;font-size:100%;" >PCFG bits</span><span style="font-size:100%;">:<br /><br /></span> <a style="font-size: 12px;" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjieBkjvkWseRBNXKnoFrUhW1rMaQjzHKj7pb5Ya-JNqohz5cdo-PkfSiYAz3etTOTwtmHAYozOsCq22fPn-OEDBUr0GYc87kWj5sqULFF_J-1SxYCk2R49ySM4t8o6XCE9Cz15SGpya-o/s1600-h/16f877_table.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 254px; font-size: 12px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjieBkjvkWseRBNXKnoFrUhW1rMaQjzHKj7pb5Ya-JNqohz5cdo-PkfSiYAz3etTOTwtmHAYozOsCq22fPn-OEDBUr0GYc87kWj5sqULFF_J-1SxYCk2R49ySM4t8o6XCE9Cz15SGpya-o/s400/16f877_table.jpg" alt="" id="BLOGGER_PHOTO_ID_5356895864206605538" border="0" height="381" width="600" /></a><br />Want 6 analog pins, no Vref ? Then PCFG bits must be set to 0b1001. What will <span style="font-size:100%;">then be the analog pins ? RA0, RA1, RA2, RA3, RA5 and RE0. "</span><span style="font-style: italic;font-size:100%;" >What if I want 7 analog pins, no Vref ?</span><span style="font-size:100%;">" You can't because you'll get a Vref pin, no choice. "</span><span style="font-style: italic;font-size:100%;" >What if I want 2 analog pins being RE1 and RE2 ?</span><span style="font-size:100%;">" You can't, because there's no such combination. So, for this </span>PIC, analog pins are dependent from each other, driven by a combination. In this case, you'll have to specify: <ul style="font-size:12px;"><li style="font-size:12px;"><span style="font-size:100%;">the </span><span style="font-weight: bold;font-size:100%;" >number of ADC channels</span><span style="font-size:100%;"> you want,</span></li><li style="font-size:12px;"><span style="font-size:100%;">and amongst them, the </span><span style="font-weight: bold;font-size:100%;" >number of Vref channels</span> </li></ul> <span style="font-style: italic;font-size:100%;" >Note:</span><span style="font-size:100%;"> this is the behavior of the </span>original Stef's lib adc_hardware.jal <br /><br />Now, let's consider 16F88. In this case, there's no such table:<br /><br /><a style="font-size: 12px;" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfOzusaKYS5372PzvvN7eB66mI2rTL81DpL753tKlsuzQkkT5SQkcrp_EOTann30eFP96z63SmXJONOddE2_1rT7Nwfq0wHwY-GbJFut3e8mdYlfcVr8-vPTfhavFTf1_tX5sKLzvMj7s/s1600-h/16f88_ans.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 112px; font-size: 12px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfOzusaKYS5372PzvvN7eB66mI2rTL81DpL753tKlsuzQkkT5SQkcrp_EOTann30eFP96z63SmXJONOddE2_1rT7Nwfq0wHwY-GbJFut3e8mdYlfcVr8-vPTfhavFTf1_tX5sKLzvMj7s/s400/16f88_ans.jpg" alt="" id="BLOGGER_PHOTO_ID_5356898246650607218" border="0" height="168" width="600" /></a><br />Mmmh... OK, there<span style="font-size:100%;"> are </span><span style="font-weight: bold;font-size:100%;" >ANS bits</span><span style="font-size:100%;">, one for each analog pins. Setting an ANS bit to 1 sets the corresponding pin to analog. This means I can set whatever pin I want to be analog. "</span><span style="font-style: italic;font-size:100%;" >I can have 3 analog pins, configured on RA0, RA4 and RB6. Freedom !</span><span style="font-size:100%;">"<br /><br />Analog pins are </span><span style="font-weight: bold;font-size:100%;" >independent</span><span style="font-size:100%;"> from each other in this case, you can do what you want. As a consequence, since it's not driven by a combination, you won't be able to specify the number of ADC channels here. Instead, you'll use </span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >set_analog_pin()</span><span style="font-size:100%;"> procedure, and if needed, the reverse </span><span style="color: rgb(0, 0, 102); font-weight: bold;font-size:100%;" >set_digital_pin()</span><span style="font-size:100%;"> procedure. These procedures takes a analog pin number as argument. Say analog pin AN5 is on pin RB6</span><span style="font-size:100%;">. To turn this pin as analog, you just have to write </span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >set_analog_pin(5)</span><span style="font-size:100%;">, because this is about analog pin AN<span style="font-weight: bold;">5</span>, and not RB<span style="font-weight: bold;">6</span>.<span style="font-style: italic;"><br /><br /></span></span><span style="font-style: italic;font-size:100%;" >Note:</span><span style="font-size:100%;"> As a consequence, these procedures don't exist when analog pins are dependent as in our first case. </span><span style="font-weight: bold;font-size:100%;" ><br /><br />Careful: </span><span style="color: rgb(153, 0, 0);font-size:100%;" >it's not because there are PCFG bits that PICs have dependent analog pins. Some have PCFG bits which act exactly the same as ANS bits (like some of recent 18F)</span><span style="font-size:100%;"><br /><br /></span> <span style="font-size:130%;"> <span style="font-weight: bold;">"Stop it, show me some code !"</span> </span><br /><br />Basically, all the logic accessing ADC module has been kept. Most of the work <span style="font-size:100%;">was about configuring the ADC module to handle all PICs. You'll find </span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >adc_read()</span><span style="font-size:100%;"> and </span><span style="color: rgb(0, 0, 102); font-weight: bold;font-size:100%;" >adc_read_low_res()</span><span style="font-size:100%;"> functions, as usual. Changes only occur while configuring the ADC module.<br /><br /><span style="font-weight: bold; color: rgb(153, 0, 0);">16F877 : dependent analog pins</span><br /><br />The following examples briefly explains how to setup ADC module when analog pins are <span style="font-style: italic;">dependent from each other</span>, using PIC 16F877.<br /><br />The following diagram is here to help knowing where <span style="font-weight: bold; color: rgb(0, 0, 153);">analog pins</span> are and where <span style="font-weight: bold; color: rgb(204, 0, 0);">Vref pins</span> are:<br /><br /></span><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwwHxSyKy2R7XUjLfQ31fgI2l9x3qCrc_-n3IsuppCnzdcEma8MtcGPr_7BXQX1IiLzDX-5KQ27Il0jZw4F1cJQhCGSu9EceqmhJyiK1bhuLMc6DshIyHi9YlBGn8DAvr_UBLpYvb_aLU/s1600-h/16F877_diagram.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 355px; height: 400px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwwHxSyKy2R7XUjLfQ31fgI2l9x3qCrc_-n3IsuppCnzdcEma8MtcGPr_7BXQX1IiLzDX-5KQ27Il0jZw4F1cJQhCGSu9EceqmhJyiK1bhuLMc6DshIyHi9YlBGn8DAvr_UBLpYvb_aLU/s400/16F877_diagram.jpg" alt="" id="BLOGGER_PHOTO_ID_5360081360972977842" border="0" /></a><br /><span style="font-size:100%;"><br /></span><span style="font-weight: bold;font-size:100%;" >Example 1</span><span style="font-size:100%;">: </span><span style="font-style: italic;font-size:100%;" >16F877, with only one analog pin, no voltage reference<br /><br /></span> <pre style="font-size:12px;"><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >-- beginning is about configuring the chip</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >-- this is the same for all examples for about 18F877</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >include 16f877</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >-- setup clock running @20MHz</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >pragma target OSC HS</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >pragma target clock 20_000_000</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >-- no watchdog</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >pragma target WDT disabled</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >pragma target LVP disabled</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >enable_digital_io()</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >include delay</span><span style="font-size:100%;"><br /><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >-- ok, now setup serial, we'll use this</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >-- to get ADC measures</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >const serial_hw_baudrate = 19_200</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >include serial_hardware</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >serial_hw_init()</span><span style="font-size:100%;"><br /><br /><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >-- ok, now let's configure ADC</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >-- we want to measure using low resolution</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >-- (that's our choice, we could use high resolution as well)</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >const bit ADC_HIGH_RESOLUTION = false</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >-- we said we want 1 analog channel...</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >const byte ADC_NCHANNEL = 1</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >-- and no voltage reference</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >const byte ADC_NVREF = 0</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >-- now we can include the library</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >-- note it's now named "adc", not "adc_hardware" anymore</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >include adc</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >-- and run the initialization step</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >adc_init()</span><span style="font-size:100%;"><br /><br /><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >-- will periodically send those chars</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >var byte measure</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >forever loop</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" > -- get ADC result, on channel 0</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" > -- this means we're currently reading on pin RA0/AN0 !</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" > measure = adc_read_low_res(0)</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" > -- send it back through serial</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" > serial_hw_write(measure)<br /><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" > -- and sleep a litte to prevent flooding serial...</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" > delay_1ms(200)</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >end loop</span><span style="font-size:100%;"><br /><br /></span></pre> <span style="font-weight: bold;font-size:100%;" >Example 2</span><span style="font-size:100%;">: </span><span style="font-style: italic;font-size:100%;" >16F877, with 5 analog pins, 1 voltage reference, that is, Vref+</span><span style="font-size:100%;"><br /><br />This is almost the same as before, except we now want 5 (analog pins) + 1 (Vref) = <span style="font-weight: bold;">6 ADC channels</span> (yes, I consider Vref+ pin as an ADC channel).<br /><br />The beginning is the same, here's just the part about ADC configuration and readings:<br /><br /></span><pre style="font-size:12px;"><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >const bit ADC_HIGH_RESOLUTION = false</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >-- our 6 ADC channel</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >const byte ADC_NCHANNEL = 6</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >-- and one Vref pin</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >const byte ADC_NVREF = 1</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >-- the two parameters could be read as:</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >-- "I want 6 ADC channels, amongst which 1 will be</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >-- reserved for Vref, and the 5 remaining ones will be</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >-- analog pins"</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >include adc</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >adc_init()<br /><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >-- will periodically send those chars</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >var byte measure</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >forever loop</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" > -- get ADC result, on channel 0</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" > -- this means we're currently reading on pin RA0/AN0 !</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" > measure = adc_read_low_res(0)</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" > -- send it back through serial</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" > serial_hw_write(measure)<br /><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" > -- same for pin RA1/AN1<br /></span><span style="font-size:100%;"><span style="font-weight: bold; color: rgb(0, 0, 102);">measure = adc_read_low_res(1)<br /></span></span><span style="font-size:100%;"><span style="font-weight: bold; color: rgb(0, 0, 102);"> serial_hw_write(measure)<br /><br /></span></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" > -- same for pin RA2/AN2<br /></span><span style="font-size:100%;"><span style="font-weight: bold; color: rgb(0, 0, 102);">measure = adc_read_low_res(2)<br /></span></span><span style="font-size:100%;"><span style="font-weight: bold; color: rgb(0, 0, 102);"> serial_hw_write(measure)<br /><br />-- pin RA3/AN3 can't be read, since it's Vref+<br /><br />-- same for pin RA5/AN4<br />-- 4 is from from "AN4" !<br /></span></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" > </span><span style="font-size:100%;"><span style="font-weight: bold; color: rgb(0, 0, 102);">measure = adc_read_low_res(4)<br /></span></span><span style="font-size:100%;"><span style="font-weight: bold; color: rgb(0, 0, 102);"> serial_hw_write(measure)<br /><br />-- same for pin RE10/AN5<br /></span></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" > </span><span style="font-size:100%;"><span style="font-weight: bold; color: rgb(0, 0, 102);">measure = adc_read_low_res(5)<br /></span></span><span style="font-size:100%;"><span style="font-weight: bold; color: rgb(0, 0, 102);"> serial_hw_write(measure)</span><br /></span><span style="font-size:100%;"><span style="font-weight: bold; color: rgb(0, 0, 102);"><br /></span></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" > -- and sleep a litte to prevent flooding serial...</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" > delay_1ms(200)</span><span style="font-size:100%;"><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:100%;" >end loop</span> </pre><br /><br /><span style="font-size:100%;"><span style="font-weight: bold; color: rgb(153, 0, 0);">16F88 : independent analog pins</span></span><br /><br />The following example is about setting up ADC module with PIC 16F88, where analog pins are independent from each other.<br /><br /><span style="font-size:100%;">The following diagram is here to help knowing where <span style="font-weight: bold; color: rgb(0, 0, 153);">analog pins</span> are and where <span style="font-weight: bold; color: rgb(204, 0, 0);">Vref pins</span> are:</span><br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9flZgs9sWFSZ9IS0zVoeFj0vtN7qqODXKFfXldDdX81u5CJgbVfqkgM5jO1l2s6GYVge-5suSG6EFdR6Vwg5ylDWb3KDXj4ZAmSn8oCi82MmTK_GXIEaMY43mdeO0kWeiEYjarDKXDh8/s1600-h/16F88_diagram.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 383px; height: 400px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9flZgs9sWFSZ9IS0zVoeFj0vtN7qqODXKFfXldDdX81u5CJgbVfqkgM5jO1l2s6GYVge-5suSG6EFdR6Vwg5ylDWb3KDXj4ZAmSn8oCi82MmTK_GXIEaMY43mdeO0kWeiEYjarDKXDh8/s400/16F88_diagram.jpg" alt="" id="BLOGGER_PHOTO_ID_5360081356528995442" border="0" /></a><br /><span style="font-weight: bold;font-size:100%;" >Example 1</span><span style="font-size:100%;">: </span><span style="font-style: italic;font-size:100%;" >16F88, analog pins on </span><span style="font-style: italic;font-size:100%;" >RA0/AN0, RA4/AN4 and RB6/AN5. No voltage reference.</span><span style="font-size:100%;"><br /><pre><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">-- beginning is about configuring the chip</span><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">include 16f88</span><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">-- We'll use internal oscillator. It work @ 8MHz</span><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">pragma target CLOCK 8_000_000</span><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">pragma target OSC INTOSC_NOCLKOUT</span><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">OSCCON_IRCF = 0b_111</span><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">pragma target WDT disabled</span><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">enable_digital_io()</span><br /><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">-- ok, now setup serial, we'll use this</span><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">-- to get ADC measures</span><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">const serial_hw_baudrate = 19_200</span><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">include serial_hardware</span><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">serial_hw_init()</span><br /><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">-- now configure ADC</span><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">const bit ADC_HIGH_RESOLUTION = false</span><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">const byte ADC_NVREF = 0</span><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">-- we can't specify a number of ADC channel here,</span><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">-- or we'll get an error !</span><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">include adc</span><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">adc_init()</span><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">-- now we declare the pin we want as analog !</span><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">set_analog_pin(0) -- RA0/AN0</span><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">set_analog_pin(4) -- RA4/AN4</span><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">set_analog_pin(5) -- RB6/AN5</span><br /><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">-- reading is then the same</span><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">var byte measure<br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);">forever loop<br /><br /></span><span style="font-weight: bold; color: rgb(0, 0, 102);"> measure = adc_read_low_res(0)</span><br /><span style="font-weight: bold; color: rgb(0, 0, 102);"> serial_hw_write(measure)</span><br /><br /><span style="font-weight: bold; color: rgb(0, 0, 102);"> measure = adc_read_low_res(4)</span><br /><span style="font-weight: bold; color: rgb(0, 0, 102);"> serial_hw_write(measure)</span><br /><br /><span style="font-weight: bold; color: rgb(0, 0, 102);"> measure = adc_read_low_res(5)</span><br /><span style="font-weight: bold; color: rgb(0, 0, 102);"> serial_hw_write(measure)</span><br /><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">end loop</span><br /><br /><br /></pre><br />Whether you would want to turn RB6/AN5 into a digital pin again, you'd just call:<br /><pre><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">set_digital_pin(5)</span><br /></pre><br /><br /><br />OK, enough for now. Next time, we'll see how it works for real, with a "Step by Step" tutorial. We'll probably use a 16F88 for this, using serial.<br /><br />As of July 19th, 2009, this ADC libraries aren't release yet (but expected to be soon). If you want to have fun with them, you'll have to get them from jallib SVN repository. See instructions here:<br /><br /><a href="http://code.google.com/p/jallib/source/checkout">http://code.google.com/p/jallib/source/checkout</a><br /><br /><br />You can also get files one by one from SVN:<br /><br /></span><ul><li><span style="font-size:100%;">everything in this directory, except old adc_hardware.jal: <a href="http://code.google.com/p/jallib/source/browse/#svn/trunk/include/peripheral/adc">http://code.google.com/p/jallib/source/browse/#svn/trunk/include/peripheral/adc</a></span></li><li><span style="font-size:100%;">last device files. For examples, <a href="http://code.google.com/p/jallib/source/browse/trunk/include/device/16f88.jal">16F88</a> and <a href="http://code.google.com/p/jallib/source/browse/trunk/include/device/16f877.jal">16F877</a><br /></span></li></ul><span style="font-size:100%;">Anyway, <a href="http://code.google.com/p/jallib/source/browse/trunk/include/device/16f877.jal">browse SVN</a> as needed :)<br /><br /><br /></span><span style="font-style: italic;font-size:100%;" ><br />Sébastien Lelong<br /></span>Sebastien Lelonghttp://www.blogger.com/profile/00317258446230687333noreply@blogger.com10tag:blogger.com,1999:blog-8299212346186005351.post-34343517113951602942009-06-29T23:55:00.039+02:002011-03-15T09:32:05.311+01:00PIC 18f14k50 USB Interface Board: Part 1<p><strong><span style="font-size:130%;">Introduction</span></strong><br />This is the first blog regarding a PIC18f14k50 USB IO board. This first session will focus on the design and building of the board, future sessions will take about software application that are being developed for this board.<br /><br />At the start of the development of the board, I had the following “bullet spec” in mind: </p><ul><li>Development “starter” board for Jal(lib) USB developement</li><li>It must have a USB 2.0 full speed connection</li><li>Must be able to use it as a USB<->RS-232 interface converter, including 2 HW handshake signal, operate as a true RS-232 interface as well have the ability to use it for 5v signals (RS-232c, so it can be used to interface board towards other test boards that don’t have a MAX-232 level converter). </li><li>Must be able to use it as a USB<->I2C interface board, either act a master or slave device</li><li>Be able to add (small) daughter boards, in order use to the board as a HW/SW development platform (e.g. Remote control receiver, remote control transmitter etc)</li><li>Homebrew friendly (easy to build, single sided PCB, no SMD component)</li><li>Cheap (~10 Euro)</li></ul><br /><br /><p><strong><span style="font-size:130%;">PIC selection</span></strong><br />The first choice is what PIC to use, since I want to use it for JAL development (which restricts me to the PIC18F series), onboard USB Serial Interface Engine (SIE), should be a thru hole device and should run with 5v IO, I got the following list from the Micrcochip website:<br /></p><br /><br /><p><span style="font-family:courier new;"><strong>Product Fam Price Fl EE RAM I/O<br /></strong><br /></span><span style="font-family:courier new;">PIC18F13K50 $1.39 8 256 512 15<br /></span><span style="font-family:courier new;">PIC18F14K50 $1.53 16 256 768 15<br /></span><span style="font-family:courier new;">PIC18F2450 $2.23 16 0 768 23<br /></span><span style="font-family:courier new;">PIC18F2455 $3.30 24 256 2048 24<br /></span><span style="font-family:courier new;">PIC18F2458 $3.58 24 256 2048 24<br /></span><span style="font-family:courier new;">PIC18F2550 $3.44 32 256 2048 24<br /></span><span style="font-family:courier new;">PIC18F2553 $4.12 32 256 2048 24<br /></span><span style="font-family:courier new;">PIC18F4450 $2.39 16 0 768 34<br /></span><span style="font-family:courier new;">PIC18F4455 $3.51 24 256 2048 35<br /></span><span style="font-family:courier new;">PIC18F4458 $3.79 24 256 2048 35<br /></span><span style="font-family:courier new;">PIC18F4550 $3.65 32 256 2048 35<br /></span><span style="font-family:courier new;">PIC18F4553 $4.33 32 256 2048 35</span><br /></p><br /><br /><p>In the past I’ve used the 18f4550, which is a nice chip, but it is a bit expensive. I also have used the 18f2450 in a couple of projects; however, the main drawback is the lack of onboard eeprom (always handy for device specific settings). The recently introduced PIC 18f14k50 appears to be a nice compromise (almost similar to the 18f2450, but it is a bit cheaper and has onboard eeprom). Even though it is a low pin count device, I think it has enough IO pins. I have considered the 13k50, which is even a dime cheaper, but the flash and memory size is quite limited and the availability is a problem. However, the board can be used for both chips.<br /></p><br /><br /><p><span style="font-size:130%;"><strong>Schematic & PCB:</strong></span><br /><br />Once the PIC was selected, the design is straightforward:<br /><br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhggiTS4wW25x8ZM9Dk3olC2ti98Z1BPhgIkgdNWSVRVFLOhImiZtld56z19TsUIdPnW2ACctZXdTiAZ2EMi_6VNt9InQ2V-6i86tByBO7kh9KpQFXelp-goOZWrxAiHd8HAO2TsqcyLp_v/s1600-h/schema.PNG"><img id="BLOGGER_PHOTO_ID_5352881662389816562" style="margin: 0px auto 10px; display: block; width: 400px; height: 284px; text-align: center;" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhggiTS4wW25x8ZM9Dk3olC2ti98Z1BPhgIkgdNWSVRVFLOhImiZtld56z19TsUIdPnW2ACctZXdTiAZ2EMi_6VNt9InQ2V-6i86tByBO7kh9KpQFXelp-goOZWrxAiHd8HAO2TsqcyLp_v/s400/schema.PNG" border="0" /></a><br /><br />I won’t go into the details of the “standard” PIC logic, consisting of the crystal (X1) + caps (C3/C4), ISCP connector (J1) and decoupling capacitor (C1).<br />There are two switches connected to the PIC, SW1 is can be used as a reset switch, SW2 is a generic switch with pull resistor. The DB-9 connector is connected via a MAX-232 level converter with the PIC (towards the internal UART PINs). The non-level shifted converted TX/RS signals are also connected to J3, in addition to the UART signals pin-5 is connected with the PWM/CCP unit of the PIC.<br /><br />The 5 volt supply of the USB connector is used to power the board; the differential USB signal lines d+/d- are directly coupled from the PIC to the USB connector. Capacitor C5 is required for the internal 3.3v regulator.<br /><br />The I2C header signals are also directly coupled with the MSSP unit, it can be used as a master or slave depending on the firmware, besides the 3 standard wires, also a 5v is available on the connector. The pull-ups can be enabled by placing the jumper (JP1).<br />Potmeter P1 is connector to AN5 of the PIC, this can be used for ADC experiments.<br /><br /><br />OK enough about the schematic. Richard Zengerink was so kind to draw the schematic and do the board layout. The board layout is depicted below, a PDF file of the layour is available in the SVN repository ( <a href="http://code.google.com/p/jallib/source/browse/trunk/project/pic18f14k50_usb_io/18F14K50+EXTRA_lay_out.pdf">18F14K50+EXTRA_lay_out.pdf</a><br />), this has the mirrored, 1:1 scale, so when printed on glossy paper with a laser printer, it can can be ironed into a copper cladded board, then etch it and drill it.<br /><br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUJoumR8XfxD71hgp-9mRguiEyOxRLoUdOQ26x4tVHpSIh67Rvlq-VGkZ_KJIZc5b_uh-HBP0cE_V8Nc9jUY9JmqhWYzOyqSftkfB7ofus47u3SKO96lihSTFvQ2sS5N1G8koN6nWcYoKy/s1600-h/pcb_layout.png"><img id="BLOGGER_PHOTO_ID_5352884578205416898" style="margin: 0px auto 10px; display: block; width: 400px; height: 250px; text-align: center;" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUJoumR8XfxD71hgp-9mRguiEyOxRLoUdOQ26x4tVHpSIh67Rvlq-VGkZ_KJIZc5b_uh-HBP0cE_V8Nc9jUY9JmqhWYzOyqSftkfB7ofus47u3SKO96lihSTFvQ2sS5N1G8koN6nWcYoKy/s400/pcb_layout.png" border="0" /></a><br /><br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjRSqQUYO9z9WkWDL7hgl_j4nI_wFVIvgktCYjkFeBraHlSop5gWeffQHNg8cYcJ7RQYI9QgCeHlMOQDbLUGUCu56ur-4LdYz5GfLskpNPHxnupdIMRyhBxf2yjRCSanUeYJA4UX1glh8q/s1600-h/pcb_components.PNG"><img id="BLOGGER_PHOTO_ID_5352885008432684130" style="margin: 0px auto 10px; display: block; width: 400px; height: 248px; text-align: center;" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjRSqQUYO9z9WkWDL7hgl_j4nI_wFVIvgktCYjkFeBraHlSop5gWeffQHNg8cYcJ7RQYI9QgCeHlMOQDbLUGUCu56ur-4LdYz5GfLskpNPHxnupdIMRyhBxf2yjRCSanUeYJA4UX1glh8q/s400/pcb_components.PNG" border="0" /></a><br /><br /><br />Building the board should not be too difficult; it took me about an hour to do the component assembly and solder it and perform some quick tests (check power connections, and check shortcuts)<br />A picture of the assembled board is depicted below:<br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHrC_hwENuUzQICHiqIaglYsSzHRtRl6Ra2yoqKF8jIoqqnlG6RPaDP2dCwXYxTMATibMqj3aIv-K1mNOR-_oiAkrPzyinZtz54OE6N1rCKKeTUEdnRjjRBehhNqilFQgOoUu8Us-xItyK/s1600-h/pcb_assembled.jpg"><img id="BLOGGER_PHOTO_ID_5352887164823142546" style="margin: 0px auto 10px; display: block; width: 400px; height: 182px; text-align: center;" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHrC_hwENuUzQICHiqIaglYsSzHRtRl6Ra2yoqKF8jIoqqnlG6RPaDP2dCwXYxTMATibMqj3aIv-K1mNOR-_oiAkrPzyinZtz54OE6N1rCKKeTUEdnRjjRBehhNqilFQgOoUu8Us-xItyK/s400/pcb_assembled.jpg" border="0" /></a><br /><br /><strong><span style="font-size:130%;">Testing the board;</span><br /></strong>The first test is to connect a PIC programmer to the ICSP connector. Program the <a href="http://code.google.com/p/jallib/source/browse/trunk/project/pic18f14k50_usb_io/led_switch_test/18f14k50_led_switch_test.hex">18f14k50_led_switch_test.hex </a> file on in the PIC and reset the board by doing a power off/on cycle (external reset is disabled in order to test SW1). The source code and Hex file are available in the <a href="http://code.google.com/p/jallib/source/browse/#svn/trunk/project/pic18f14k50_usb_io">jallib SVN repository</a><br /><br /><br />The application will turn on both LEDs for about 5 seconds, afterwards it starts to blink both LEDs every second. When SW1 is pressed, LED1 will stop blinking, when SW2 is pressed, LED2 will stop blinking.<br /><br />Once this is working, we can confirm that ICSP, Power, oscillator, SW1, SW2, LED1 and LED2 are properly mounted.<br /><br />The next step is to download the bootloader. Select the <a href="http://code.google.com/p/jallib/source/browse/trunk/project/pic18f14k50_usb_io/bootloader/18f14k50_usb_bootloader.hex">18f14k50_usb_bootloader.hex </a> in the ICSP programmer, and program the hex file. Remove the ICSP connector (since there shared with the USB lines), connect the USB connector with a USB cable with the Host computer, when plugging in the USB connector, hold down SW2 (program button)<br /><br />If everything went ok, after a couple of seconds the Host computer will detect the USB bootloader device, it will ask for a driver. Navigate to the directory where the USB driver bootloader driver files are located, ignore the certificate warning by selecting the continue button. <a href="https://docs.google.com/leaf?id=0B_Tqf61BWjgbZTEyYjhiYjYtNzUzZC00YjM5LTkwNDAtNmZlYzQ2MDhiMTc4&hl=en&authkey=CLWC0cYE">MCHPUSB Custom Driver.zip</a> contains required drivers. Unzip the package to a local drive, the drivers are located in the MCHPUSB Driver\Release directory</p><p>Once the drivers are installed, you can use the PDFSUSB.exe applicatio, contained in <a href="https://docs.google.com/leaf?id=0B_Tqf61BWjgbYzUyOTBhMTgtZDMxMy00ZmY1LWIwMzktMTkxODM4OWQ4ZjMz&sort=name&layout=list&num=50">Pdfsusb.zip</a> archive. After you unzip the file and launch the application, select the dropdown arrow of the combo box.<br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPVWDfuNhCPU-gCcHj3K-U_H53HaWWa2e68mOt3evrn90y9xE-lUWptwRRqN2hCHEFzm7EkXTSlELmAf-QlzISCDDv4N79gQqEqm2yr7Z-xjV0Glts6giMUAuSOt23X14AFtH69ilwL1JT/s1600-h/dwnl_screen_1.PNG"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 348px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPVWDfuNhCPU-gCcHj3K-U_H53HaWWa2e68mOt3evrn90y9xE-lUWptwRRqN2hCHEFzm7EkXTSlELmAf-QlzISCDDv4N79gQqEqm2yr7Z-xjV0Glts6giMUAuSOt23X14AFtH69ilwL1JT/s400/dwnl_screen_1.PNG" alt="" id="BLOGGER_PHOTO_ID_5352894302674712898" border="0" /></a><br /><br />You should see the PICDEM FS USB 0 (BOOT) option, select it (see also screenshot). After selection, it should update the status bar, it will depict the version number (1.20) of the firmware.<br /><br />When using the bootloader, you need to add the following setting when compiling a JAL file in cooperation with the bootloader:<br /><br />-loader18 –no-fuse<br /><br />The JAL compiler will generate special startup and interrupt code if the loader18 option is specified, the no-fuse is used to avoid overwriting wrong fuses which can mess up the bootloader (although the PDFSUSB will also emit a warning, and ask for confirmation when overwriting the fuses)<br /><br /><br />So far for part1, next blog(s) will discuss how to use the board as a USB<->RS-232 convert, use it as a USB driven I2C master or slave device and show how to make a small daughter board to capture and generate remote control infrared signals.<br /><br />Hope you like it, feeback is always welcome…<br /><br />Albert Faber & Richard Zengerink<br /><br /><br /><br /></p><p></p>Alberthttp://www.blogger.com/profile/07474528874165692590noreply@blogger.com27tag:blogger.com,1999:blog-8299212346186005351.post-69620578005411681932009-04-11T10:49:00.025+02:002009-06-04T20:52:55.243+02:00Step by step: interfacing a Sharp GP2D02 IR rangerSharp IR rangers are widely used out there. There are many different references, depending on the beam pattern, the minimal and maximal distance you want to be able to get, etc... The way you got results also make a difference: either <span style="font-weight: bold;">analog</span> (you'll get a voltage proportional to the distance), or digital (you'll directly get a <span style="font-weight: bold;">digital</span> value). This <a href="http://www.acroname.com/robotics/info/articles/sharp/sharp.html">nice article</a> will explain these details (and now I know GP2D02 seems to be discontinued...)<br /><br /><br /><span style="font-size:130%;"><span style="font-weight: bold;">Overview of GP2D02 IR ranger</span></span><br /><br />GP2D02 IR ranger is able to measure distances between approx. 10cm and 1m. Results are available as digital values you can access through a dedicated protocol. One pin, <span style="font-weight: bold;">Vin</span>, will be used to act on the ranger. Another pin,<span style="font-weight: bold;"> Vout</span>, will be read to determine the distance. Basically, getting a distance involves the following:<br /><br /><ol><li>First you wake up the ranger and tell it to perform a distance measure</li><li>Then, for each bit, you read Vout in order to reconstitute the whole byte, that is, the distance</li><li>finally, you switch off the ranger</li></ol><br />The following timing chart taken from the datasheet will explain this better.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEja2KcQzQqScwYYjlISBlS5Tq9jwsHtZ5LAsTy7-kweIURXxxWwZU_BhqNnNr7IjWbLDKKkiOXE3yl9OPE74rMWz4VNZP4BIFt0IGKFd7WJUdzzykvrjpAfhePZ3BqKmN1ecdN6t8kxoyA/s1600-h/timingchart.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 210px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEja2KcQzQqScwYYjlISBlS5Tq9jwsHtZ5LAsTy7-kweIURXxxWwZU_BhqNnNr7IjWbLDKKkiOXE3yl9OPE74rMWz4VNZP4BIFt0IGKFd7WJUdzzykvrjpAfhePZ3BqKmN1ecdN6t8kxoyA/s400/timingchart.jpg" alt="" id="BLOGGER_PHOTO_ID_5323358894034207282" border="0" /></a><br /><br /><span style="font-style: italic;">Note</span>: the distances obtained from the ranger aren't linear, you'll need some computation to make them so.<br /><br /><span style="font-weight: bold;">Sharp GP2D02 IR ranger</span> looks like this:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxwDdvEwo5rNyhHxxD6ClMKdQg6fRcTsGn193hAmfBxmTBqwhljN9a0M7ihb9aPIqCamGbrecPFG0TsuYvasUhqD1nZycernsjiKeHVmOX3hQe4gp8R6K6Q4FrQIzdOueGX7VcbQY09T8/s1600-h/wires.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxwDdvEwo5rNyhHxxD6ClMKdQg6fRcTsGn193hAmfBxmTBqwhljN9a0M7ihb9aPIqCamGbrecPFG0TsuYvasUhqD1nZycernsjiKeHVmOX3hQe4gp8R6K6Q4FrQIzdOueGX7VcbQY09T8/s400/wires.jpg" alt="" id="BLOGGER_PHOTO_ID_5342231294100400066" border="0" /></a><br /><ul><li><span style="font-weight: bold; color: rgb(255, 0, 0);">Red </span>wire is for +5V</li><li><span style="font-weight: bold;">Black </span>wire ground</li><li><span style="font-weight: bold; color: rgb(0, 153, 0);">Green </span>wire is for Vin pin, used to control the sensor<br /></li><li><span style="font-weight: bold; color: rgb(255, 204, 102);">Yellow </span>wire is for Vout pin, from which 8-bits results read<br /></li></ul><span style="font-style: italic;">(make a mental note of this...)</span><br /><br /><br /><span style="font-size:130%;"><span style="font-weight: bold;">Interfacing the Sharp GP2D02 IR ranger</span></span><br /><br />Interfacing such a sensor is quite straight forward. The only critical point is <span style="font-weight: bold;">Vin</span> ranger pin can't handle high logic level of the PIC's output, <span style="font-style: italic;">this level mustn't exceed 3.3 volts</span>. A <span style="font-weight: bold;">zener diode</span> can be used to limit this level.<br /><br /><span style="font-style: italic;"><span style="font-weight: bold;">Note</span>: be careful while connecting this diode. Don't forget it, and don't put it in the wrong side. You may damage your sensor. And I'm not responsible for ! You've been warned... That's said, I already forgot it, put it in the wrong side, and thought I'd killed my GP2D02, but this one always got back to life. Anyway, be cautious !</span><br /><br />Here's the whole schematic. The goal here is to collect data from the sensor, and light up a LED, more or less according to the read distance. That's why we'll use a LED driven by PWM.<br /><br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaBBPQ9DKfAsx2DMPtFzGFIp_Gnh8ooji2n4oBW5RCreRuYELsGWB5TQMBQ-JIuIfxJkfAjIib15N-0F_G51YRptpSZ72gzp5peQuoBCk7kpa_XUwlRcPw-WflwNMLf_GXrUxdjgOGtzM/s1600-h/gp2d02_schematics.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 296px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaBBPQ9DKfAsx2DMPtFzGFIp_Gnh8ooji2n4oBW5RCreRuYELsGWB5TQMBQ-JIuIfxJkfAjIib15N-0F_G51YRptpSZ72gzp5peQuoBCk7kpa_XUwlRcPw-WflwNMLf_GXrUxdjgOGtzM/s400/gp2d02_schematics.png" alt="" id="BLOGGER_PHOTO_ID_5343546689819071106" border="0" /></a><br /><br />Here's the ranger with the diode soldered on the <span style="color: rgb(0, 153, 0);">green </span>wire (which is Vin pin, using your previously created mental note...):<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5O0oOBroV9B5ilJIO5GUkn6E_pfII9-L9No-UDQyQ-Fef5vonXLUhcAv0H57R3KLlB2yFMYzi-MWXhJN0j8dLKXSBQiM1Xypu5AS9VsfAuoLCWwxsrlnLoP-dpDQ6jwRlHZ4BVh9g9zE/s1600-h/diode.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5O0oOBroV9B5ilJIO5GUkn6E_pfII9-L9No-UDQyQ-Fef5vonXLUhcAv0H57R3KLlB2yFMYzi-MWXhJN0j8dLKXSBQiM1Xypu5AS9VsfAuoLCWwxsrlnLoP-dpDQ6jwRlHZ4BVh9g9zE/s400/diode.jpg" alt="" id="BLOGGER_PHOTO_ID_5342231294098946194" border="0" /></a><br /><br />I've also added thermoplastic rubber tubes, to cleanly join all the wires:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuHxq9ATe9qYa2U5VAM4cipHcOwX7rPwUamEMIrnzHEht8DYg3EpiVJqp_4IkMV9Qopv4-mD9e_33vzfAK7vE315YOrB-jLBtngyeyGRHEDHyzzQBVPmGDOvePOqijcrWDOmPSD63b1MM/s1600-h/cable.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuHxq9ATe9qYa2U5VAM4cipHcOwX7rPwUamEMIrnzHEht8DYg3EpiVJqp_4IkMV9Qopv4-mD9e_33vzfAK7vE315YOrB-jLBtngyeyGRHEDHyzzQBVPmGDOvePOqijcrWDOmPSD63b1MM/s400/cable.jpg" alt="" id="BLOGGER_PHOTO_ID_5342231296750460802" border="0" /></a><br /><br />Finally, in order to easily plug/unplug the sensor, I've soldered nice polarized connectors:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidgTzicO0ABf3fi-wfUo0y6deIaFgEpfD9LYHiRnMKSGT9H2CP88XRZTfPfCz6w4BP9GU5mnvAA4qUlhwTdcuKrZh_gaej5_L0ohoktSlKwoMNqJ_-DU8RKvWoZ4wwSLUSak2zqPNbnY0/s1600-h/connectors.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidgTzicO0ABf3fi-wfUo0y6deIaFgEpfD9LYHiRnMKSGT9H2CP88XRZTfPfCz6w4BP9GU5mnvAA4qUlhwTdcuKrZh_gaej5_L0ohoktSlKwoMNqJ_-DU8RKvWoZ4wwSLUSak2zqPNbnY0/s400/connectors.jpg" alt="" id="BLOGGER_PHOTO_ID_5342231300620012802" border="0" /></a><br /><br /><span style="font-size:130%;"><span style="font-weight: bold;">Writing the program</span><span style="font-weight: bold;"><br /><br /><span style="font-size:100%;"><span style="font-weight: bold;"></span></span></span></span>jallib >=0.3 contains a library, <span style="font-weight: bold; color: rgb(0, 0, 153);">ir_ranger_gp2d02.jal</span>, used to handle this kind of rangers. The setup is quite straight forward: just declare your Vin and Vout pins, and pass them to the <span style="color: rgb(0, 0, 153); font-weight: bold;">gp2d02_read_pins()</span>. This function returns the distance as a raw value. Directly passing pins allows you to have multiple rangers of this type (many robots have many of them arranged in the front and back sides, to detect and avoid obstacles).<br /><br />Using PWM libs, we can easily make our LED more or less bright. In the mean time, we'll also transmit the results through a serial link.<br /><br /><pre><span style="color: rgb(0, 0, 153); font-weight: bold;">var volatile bit gp2d02_vin is pin_a4</span><br /><span style="color: rgb(0, 0, 153); font-weight: bold;">var volatile bit gp2d02_vout is pin_a6</span><br /><span style="color: rgb(0, 0, 153); font-weight: bold;">var bit gp2d02_vin_direction is pin_a4_direction</span><br /><span style="color: rgb(0, 0, 153); font-weight: bold;">var bit gp2d02_vout_direction is pin_a6_direction</span><br /><span style="color: rgb(0, 0, 153); font-weight: bold;">include ir_ranger_gp2d02</span><br /><span style="color: rgb(0, 0, 153); font-weight: bold;">-- set pin direction (careful: "vin" is the GP2D02 pin's name,</span><br /><span style="color: rgb(0, 0, 153); font-weight: bold;">-- it's an input for GP2D02, but an output for PIC !)</span><br /><span style="color: rgb(0, 0, 153); font-weight: bold;">gp2d02_vin_direction = output</span><br /><span style="color: rgb(0, 0, 153); font-weight: bold;">gp2d02_vout_direction = input</span><br /><br /><span style="color: rgb(0, 0, 153); font-weight: bold;">var byte measure</span><br /><span style="color: rgb(0, 0, 153); font-weight: bold;">forever loop</span><br /><span style="color: rgb(0, 0, 153); font-weight: bold;"> -- read distance from ranger num. 0</span><br /><span style="color: rgb(0, 0, 153); font-weight: bold;"> measure = gp2d02_read_pins(gp2d02_vin,gp2d02_vout)</span><br /><span style="color: rgb(0, 0, 153); font-weight: bold;"> -- results via serial</span><br /><span style="color: rgb(0, 0, 153); font-weight: bold;"> serial_hw_write(measure)</span><br /><span style="color: rgb(0, 0, 153); font-weight: bold;"> -- now blink more or less</span><br /><span style="color: rgb(0, 0, 153); font-weight: bold;"> pwm1_set_dutycycle(measure)</span><br /><span style="color: rgb(0, 0, 153); font-weight: bold;">end loop</span><br /><br /></pre>Note: I could directly pass <span style="font-weight: bold; color: rgb(0, 0, 153);">pin_A4</span> and <span style="color: rgb(0, 0, 153); font-weight: bold;">pin_A6</span>, but to avoid confusion, I prefer using <span style="font-style: italic;">aliases</span>.<br /><br />A sample, <span style="color: rgb(0, 0, 153); font-weight: bold;">16f88_ir_ranger_gp2d02.jal</span>, is <a href="http://code.google.com/p/jallib/source/browse/trunk/sample/16f88_ir_ranger_gp2d02.jal">available </a>in <a href="http://code.google.com/p/jallib/source/browse/">jallib SVN repository</a>, and also in jallib released packages, starting from version 0.3. You can access downloads <a href="http://code.google.com/p/jallib/downloads/list">here</a>.<br /><br /><br /><span style="font-size:130%;"><span style="font-weight: bold;">Building the whole on a breadboard<br /></span></span><br />Putting all this stuff on a breadboard should be easy. Just follow the schematics :)<br /><br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2TeUEjScQG4IhN3-xi389uT0FH6OlYzmjGP06f3bTwDWUwmfVdIthbwVEOoJ853w5cZpHI4QFquuRLnci0Kmod3XFoPnTDRi-4y_tc-Fcc-5Eopqrv2iVGiMF05EsSxcwwokmhUQkoUo/s1600-h/circuit.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2TeUEjScQG4IhN3-xi389uT0FH6OlYzmjGP06f3bTwDWUwmfVdIthbwVEOoJ853w5cZpHI4QFquuRLnci0Kmod3XFoPnTDRi-4y_tc-Fcc-5Eopqrv2iVGiMF05EsSxcwwokmhUQkoUo/s400/circuit.jpg" alt="" id="BLOGGER_PHOTO_ID_5342231307634588674" border="0" /></a><br /><br />I usually power two tracks on the side, used for the PIC and for the ranger:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQMuuKT4Ds64ePyHrQa_jdyw0YAMfhYAzgfUiRo9IvMW3LmbXUcIBiKCKGO3j1eWf31_iwYIZ6u34AjRVBzHi0X7hhkV6TwQqeZy3Qvu9wYg2ST0T5FYRKnvc0eOaVG45-_WNwoFiBZqQ/s1600-h/circuit_ranger.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQMuuKT4Ds64ePyHrQa_jdyw0YAMfhYAzgfUiRo9IvMW3LmbXUcIBiKCKGO3j1eWf31_iwYIZ6u34AjRVBzHi0X7hhkV6TwQqeZy3Qvu9wYg2ST0T5FYRKnvc0eOaVG45-_WNwoFiBZqQ/s400/circuit_ranger.jpg" alt="" id="BLOGGER_PHOTO_ID_5342231528279665746" border="0" /></a><br />Using the same previously created mental note, I connected the <span style="color: rgb(255, 204, 0);">yellow Vout</span> pin using a <span style="color: rgb(255, 204, 51);">yellow wire</span>, and the <span style="color: rgb(51, 204, 0);">green Vin</span> pin using a <span style="color: rgb(51, 204, 0);">green wire</span>...<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6Sq1QA7CA1bkxBhQKa2Oal0tLGr1YF3hRjS3LKuukhu08CtpcNPsPkR79utoL7F24MpXxLUhztzKBxMvbUz-UTi5kqT1Rm6-ZATVtWaAldw_Squ9JMjt7u0kKG83k3iMTgMi7GszQ7SA/s1600-h/circuit_pic.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6Sq1QA7CA1bkxBhQKa2Oal0tLGr1YF3hRjS3LKuukhu08CtpcNPsPkR79utoL7F24MpXxLUhztzKBxMvbUz-UTi5kqT1Rm6-ZATVtWaAldw_Squ9JMjt7u0kKG83k3iMTgMi7GszQ7SA/s400/circuit_pic.jpg" alt="" id="BLOGGER_PHOTO_ID_5342231524473982018" border="0" /></a><br /><span style="font-size:130%;"><br /><span style="font-weight: bold;">Testing (and the video)</span></span><br /><br />Time to test this nice circuit ! Power the whole, and check no smoke is coming from the PIC or (and) the ranger. Now get an object, like you hand, more or less closed to the ranger and observe the LED, or the serial output... Sweet !<br /><br /><br /><br /><object height="344" width="425"><param name="movie" value="http://www.youtube.com/v/l5AZwv7LzyM&hl=fr&fs=1"><param name="allowFullScreen" value="true"><param name="allowscriptaccess" value="always"><embed src="http://www.youtube.com/v/l5AZwv7LzyM&hl=fr&fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" height="344" width="425"></embed></object><br /><br /><br /><br /><br /><span style="font-style: italic;">Sébastien Lelong</span>Sebastien Lelonghttp://www.blogger.com/profile/00317258446230687333noreply@blogger.com3tag:blogger.com,1999:blog-8299212346186005351.post-2921063950059965792009-02-14T09:53:00.013+01:002009-06-04T20:54:13.926+02:00Step by Step: having fun with PWM and a piezo buzzer (or a speaker) (part 2)The <a href="http://jallib.blogspot.com/2009/02/step-by-step-having-fun-with-pwm-and.html">last time</a>, we had fun by controlling the brightness of a LED, using PWM. This time, we're going to have even more fun with a <span style="font-style: italic;">piezo buzzer</span>, or a small <span style="font-style: italic;">speaker</span>.<br /><br />If you remember, with PWM, you can either vary the <span style="font-weight: bold;">duty cycle</span> or the <span style="font-weight: bold;">frequency</span>. Controlling the brightness of a LED, ie. produce a variable voltage <span style="font-style: italic;">on the average</span>, can be done by having a constant frequency (high enough) and vary the duty cycle. This time, this will be the opposite: we'll have a <span style="font-style: italic;">constant duty cycle</span>, and <span style="font-style: italic;">vary the frequency</span>.<br /><br /><br /><span style="font-size:130%;"><span style="font-weight: bold;">What is a piezo buzzer ? </span></span><br /><br />It's a "component" with a material having <span style="font-style: italic;">piezoelectric</span> ability. <a href="http://en.wikipedia.org/wiki/Piezoelectricity">Piezoelectricity</a> is the ability for a material to produce voltage when it get distorted. The reverse is also true: <span style="font-style: italic;">when you produce a voltage, the material gets distorted</span>. When you stop producing a voltage, it gets back to its original shape. If you're fast enough with this on/off voltage setting, then <span style="font-style: italic;">the piezo will start to oscillate</span>, and will <span style="font-weight: bold;">produce sound</span>. How sweet...<br /><br /><br /><span style="font-size:130%;"><span style="font-weight: bold;">Constant duty cycle ? Why ?</span></span><br /><br />So we now know why we need to vary the frequency. This will make the piezo oscillates more and less, and produces sounds at different levels. If you produce a 440Hz frequency, you'll get a nice <a href="http://en.wikipedia.org/wiki/A440">A3</a>.<br /><br />But why having a <span style="font-style: italic;">constant duty cycle</span> ? What is the role of the duty cycle in this case ? Remember: when making a piezo oscillate, it's not the amount of volts which is important, it's how you turn the voltage on/off: <ul><li><span style="font-weight: bold;">when setting the duty cycle to 10%</span>: during a period, piezo will get distorted 10% on the time, and remain inactive 90% on the time. <span style="font-style: italic;">The oscillation proportion is low</span>.</li><li><span style="font-weight: bold;">when setting the duty cycle to 50%</span>: the piezo is half distorted, half inactive. <span style="font-style: italic;">The oscillation proportion is high</span>, because the piezo oscillates at the its maximal amplitude, it's half and equally distorted and inactive. </li><li><span style="font-weight: bold;">when setting the duty cycle to 90%</span>: the piezo will get distorted during 90% of a period, then nothing. <span style="font-style: italic;">The oscillation proportion is low again</span>, because the proportion between distortion and inactivity is not equal. </li></ul>(I guess this is about energy or something like that. One guru could explain the maths here...)<br /><br />So, to summary, what is the purpose of the duty cycle in our case ? The <span style="font-weight: bold;">volume</span> ! You can vary the volume of the sound by modifying the duty cycle. 0% will produce no sounds, 50% will be the max volume. Between 50% and 100% is the same as between 0% and 50%. So, when I say when need a constant duty cycle, it's not that true, it's just that we'll set it at 50%, so the chances we hear something are high :)<br /><br /><br /><span style="font-size:130%;"><span style="font-weight: bold;">Let's produce sounds ! </span></span><br /><br />The schematics will use is exactly the same as on the previous post with the LED, except the LED is replaced with a piezo buzzer, like this:<br /><br /><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhG45zp3SuNk6S4MyQGI9BnczvrFSnqAmvdV-4gUP0-uGLutJPB4Tf-892GzU93Ec6VqWmqaG3XwCfSNfwzUIVpj6ZbB8i6uUAKxHIbq8jhPtOrpPc4zTLai7IO1fWdpPqxj6LUWsiQTwg/s1600-h/pwm_sound.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhG45zp3SuNk6S4MyQGI9BnczvrFSnqAmvdV-4gUP0-uGLutJPB4Tf-892GzU93Ec6VqWmqaG3XwCfSNfwzUIVpj6ZbB8i6uUAKxHIbq8jhPtOrpPc4zTLai7IO1fWdpPqxj6LUWsiQTwg/s400/pwm_sound.jpg" alt="" id="BLOGGER_PHOTO_ID_5302589387059494738" border="0" /></a><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhftdpUEvyhmC0PliOCOZpDZK5fYrzS9NyWTUhxeLa6AsxdIIuIH_yaupbHvoKpPFpX0w5mStqEzAj2fQwfvfR0OmL2qzf88qptmV_Lh4_6osPmo_nNdR6KfM-Z4hji6ZWoPLLu4bKO9YA/s1600-h/pwm_sound_piezo.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 240px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhftdpUEvyhmC0PliOCOZpDZK5fYrzS9NyWTUhxeLa6AsxdIIuIH_yaupbHvoKpPFpX0w5mStqEzAj2fQwfvfR0OmL2qzf88qptmV_Lh4_6osPmo_nNdR6KfM-Z4hji6ZWoPLLu4bKO9YA/s400/pwm_sound_piezo.jpg" alt="" id="BLOGGER_PHOTO_ID_5302589392251462434" border="0" /></a><br /></div><br />By the way, how to observe the "duty cycle effect" on the volume ? Just program your PIC with the previous experiment one, which control the brightness of a LED, and power on the circuit. I wanted to show a video with sounds, but the frequency is too high, my camera can't record it...<br /><br />Anyway, that's a little bit boring, we do want sounds...<br /><br /><span style="font-size:130%;"><br /><span style="font-weight: bold;">Writing the software</span></span><br /><br />The software part has a lot of similarities with the <a href="http://jallib.blogspot.com/2009/02/step-by-step-having-fun-with-pwm-and.html">previous experiment</a>. The initialization is the same, I let you have a look. Only the <span style="font-weight: bold; color: rgb(51, 0, 153);">forever loop </span>has changed:<br /><br /><pre><span style="font-weight: bold; color: rgb(51, 0, 153);">var dword counter = 0</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);">forever loop</span><br /><br /><span style="font-weight: bold; color: rgb(51, 0, 153);"> for 100_000 using counter loop</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);"> pwm_set_frequency(counter)</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);"> -- Setting @50% gives max volume</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);"> -- must be re-computed each time the frequency</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);"> -- changes, because it depends on PR2 value</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);"> pwm1_set_percent_dutycycle(50)</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);"> end loop</span><br /><br /><span style="font-weight: bold; color: rgb(51, 0, 153);">end loop</span><br /></pre><br />Quite straightforward: <ul><li>we "explore" frequencies between 0 and 100 000 Hz, using a <span style="font-weight: bold; color: rgb(51, 0, 153);">counter</span></li><li>we use <span style="font-weight: bold; color: rgb(51, 0, 153);">pwm_set_frequency(counter)</span> to set the frequency, in Hertz. It takes a dword as parameter (ie. you can explore a lot of frequencies...)</li><li>finally, as we want a 50% duty cycle, and since its value is different for each frequency setting, we need to re-compute it on each loop. </li></ul><span style="font-size:85%;"> Note: jallib's PWM libraries are coming from a "heavy refactoring" of Guru Stef Mientki's PWM library. While integrating it to jallib, we've modified the library so frequencies can be set and changed during program execution. This wasn't the case before, because the frequency was set as a constant.</span><br /><br /><br />So, how does this look like ? Hope you'll like the sweet melody :)<br /><br /><object height="344" width="425"><param name="movie" value="http://www.youtube.com/v/xZ9OhQUKGtQ&hl=en&fs=1"><param name="allowFullScreen" value="true"><param name="allowscriptaccess" value="always"><embed src="http://www.youtube.com/v/xZ9OhQUKGtQ&hl=en&fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" height="344" width="425"></embed></object><br /><br /><br /><br /><span style="font-size:130%;"><span style="font-weight: bold;">"Where can I download the files ?"</span></span><br /><br />As usual, you'll need the <a href="http://code.google.com/p/jallib/downloads/list">last jallib pack</a> (at least 0.2 version). You'll also find the exact code we used <a href="http://jallib.googlegroups.com/web/blog_16f88_pwm_sound.jal">here</a>.<br /><br /><br /><br /><br /><span style="font-style: italic;">Sébastien Lelong</span>Sebastien Lelonghttp://www.blogger.com/profile/00317258446230687333noreply@blogger.com3tag:blogger.com,1999:blog-8299212346186005351.post-25359878444579998532009-02-07T11:21:00.020+01:002009-02-08T16:31:06.795+01:00Step by Step: having fun with PWM and a LED (part 1)<span style="font-size:130%;"><span style="font-style: italic; font-weight: bold;">Part 1 : controlling the brightness of a LED</span></span><br /><br /><br />In this "Step-by-Step" tutorial, we're going to (try to) have some fun with <span style="font-weight: bold;">PWM</span>. PWM stands for <a href="http://en.wikipedia.org/wiki/PWM"><span style="font-weight: bold;">Pulse Width Modulation</span></a>, and is quite weird when you first face this (this was at least my first feeling).<br /><br /><br /><span style="font-weight: bold;font-size:130%;" >So, how does PWM look like ?...</span><br /><br />PWM is about switching one pin (or more) <span style="font-style: italic;">high</span> and <span style="font-style: italic;">low</span>, at different <span style="font-style: italic;">frequencies</span> and <span style="font-style: italic;">duty cycles</span>. This is a on/off process. You can either vary:<br /><ul><li> the <span style="font-weight: bold;">frequency</span>,<br /></li><li> or the <span style="font-weight: bold;">duty cycle</span>, that is the proportion where the pin will be high<br /></li></ul><br /><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6iiZv_HjceGnNrXZ46Au9M1kI8F5L4oBFEqMq5zPMMiiOYZoRfzZFif-bv7n5Gq9x6_sH2MAtop5X6iu9fbdhWPSGr6lICdMGLbaxYTmDrRqBvuDvmXI6WEW4bUfnValbFDpY9hf_PsU/s1600-h/pwm_freq.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 162px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6iiZv_HjceGnNrXZ46Au9M1kI8F5L4oBFEqMq5zPMMiiOYZoRfzZFif-bv7n5Gq9x6_sH2MAtop5X6iu9fbdhWPSGr6lICdMGLbaxYTmDrRqBvuDvmXI6WEW4bUfnValbFDpY9hf_PsU/s400/pwm_freq.png" alt="" id="BLOGGER_PHOTO_ID_5300039903782386946" border="0" /></a><br /><span style="font-style: italic;">Both have a 50% duty cycle (50% on, 50% off),<br />but the upper one's frequency is twice the bottom<br /></span></div><br /><br /><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjT16qvC_y7V1_dUH1A9h0Bn0AMxsl-B2qh5gvK3J7iU_wJfF3YBkmhNMgK6NO3s5KgrtMpIOo7iz-DX19kUrjqsXpzWrx25MmyP1zjFHpczV0HG1CSWyoPqxYImWSwThGewiId_er5AyI/s1600-h/pwm_duty.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 230px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjT16qvC_y7V1_dUH1A9h0Bn0AMxsl-B2qh5gvK3J7iU_wJfF3YBkmhNMgK6NO3s5KgrtMpIOo7iz-DX19kUrjqsXpzWrx25MmyP1zjFHpczV0HG1CSWyoPqxYImWSwThGewiId_er5AyI/s400/pwm_duty.png" alt="" id="BLOGGER_PHOTO_ID_5300039900644493122" border="0" /></a><br /><span style="font-style: italic;">Three different duty cycle (10%, 50% and 90%),<br />all at the same frequency<br /><br /></span></div><br />But what is PWM for ? What can we do with it ? Many things, like:<br /><ul><li>producing variable voltage (to control DC motor speed, for instance)<br /></li><li>playing sounds: duty cycle is constant, frequency is variable<br /></li><li>playing PCM wave file (PCM is Pulse Code Modulation)</li><li>...</li></ul><br /><br /><span style="font-weight: bold;font-size:130%;" >One PWM channel + one LED = fun</span><br /><br />For now, and for this first part, we're going to see how to <span style="font-style: italic;">control the brightness of a LED</span>. If simply connected to a pin, it will light at its max brightness, because the pin is "just" high (5V).<br /><br />Now, if we connect this LED on a PWM pin, maybe we'll be able to control the brightness: as previously said, <span style="font-style: italic;">PWM can be used to produce variable voltages</span>. If we provide half the value (2.5V), maybe the LED will be half its brightness (though I guess the relation between voltage and brightness is not linear...). Half the value of 5V. How to do this ? Simply <span style="font-weight: bold;">configure the duty cycle to be 50% high, 50% low</span>.<br /><br />But we also said <span style="font-style: italic;">PWM is just about switching a pin on/off</span>. That is, either the pin will be 0V, or 5V. So how will we be able to produce 2.5V ? Technically speaking, we won't be able to produce a real 2.5V, but if PWM frequency is high enough, then, on the average, and from the LED's context, it's as though the pin outputs 2.5V.<br /><br /><span style="font-size:130%;"><br /></span><span style="font-weight: bold;font-size:130%;" >Building the whole</span><br /><br />Enough theory, let's get our hands dirty. Connecting a LED to a PWM pin on a 16f88 is quite easy. This PIC has quite a nice feature about PWM, it's possible to select which pin, between <span style="font-style: italic;">RB0</span> and <span style="font-style: italic;">RB3</span>, will carry the PWM signals. Since I use <a href="http://www.etc.ugal.ro/cchiculita/software/picbootloader.htm">tinybootloader</a> to upload my programs, and since tiny's fuses are configured to select the RB0 pin, I'll keep using this one (if you wonder why tinybootloader interferes here, <a href="http://jallib.blogspot.com/2009/01/common-pitfall-setting-up-registers.html">read this post</a>).<br /><br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOg8i-t2E4L058CZtvmkR3cx5odtF25hLeCfswCvizvz2PYKCfFYM71nMnkfVIpQow3iAjvWUmP6drX91Gz0cSF7yDLBG6eTMTQ9hvKimVqEJABx_NPHNxdLiBOCFojY5rUmvd_BYbMo8/s1600-h/pwm_led_schematics.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 384px; height: 378px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOg8i-t2E4L058CZtvmkR3cx5odtF25hLeCfswCvizvz2PYKCfFYM71nMnkfVIpQow3iAjvWUmP6drX91Gz0cSF7yDLBG6eTMTQ9hvKimVqEJABx_NPHNxdLiBOCFojY5rUmvd_BYbMo8/s400/pwm_led_schematics.png" alt="" id="BLOGGER_PHOTO_ID_5300367561253289826" border="0" /></a><br /><br />On a breadboard, this looks like this:<br /><br /><br /><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4Mf8wQsscY9gO8PAcV1eXgX_d1VcBzToBeFsLSkKaMuvT5VHUFgR8wWJ8dPLoVkEiKEsdLnoykMR2fFUBm7mVLWRtll2sBHBTYuxkpd5gR8Sy5_ybkXNl762OO8tBJnUu5DhTLQ6BYq8/s1600-h/pwm_led_breadboard.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4Mf8wQsscY9gO8PAcV1eXgX_d1VcBzToBeFsLSkKaMuvT5VHUFgR8wWJ8dPLoVkEiKEsdLnoykMR2fFUBm7mVLWRtll2sBHBTYuxkpd5gR8Sy5_ybkXNl762OO8tBJnUu5DhTLQ6BYq8/s400/pwm_led_breadboard.jpg" alt="" id="BLOGGER_PHOTO_ID_5300373469267141506" border="0" /></a><span style="font-style: italic;">The connector brings +5V on the two bottom lines<br />(+5V on line A, ground on line B).<br /></span></div><br /><br /><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBNd8fLqCdkuXAsOMUQQGYJBtw_sh66_VC-9P-2FP9PDSlPCyi1t1O07TpzzaRl3s6fe4K1DAJ_JfxzIf9F3bDTkBCTD2ovKJ__hF5YyvTmZbg2dE-U3HDT2Z40A4J5fFAc-MdBrQ1wpQ/s1600-h/pwm_led_details.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBNd8fLqCdkuXAsOMUQQGYJBtw_sh66_VC-9P-2FP9PDSlPCyi1t1O07TpzzaRl3s6fe4K1DAJ_JfxzIf9F3bDTkBCTD2ovKJ__hF5YyvTmZbg2dE-U3HDT2Z40A4J5fFAc-MdBrQ1wpQ/s400/pwm_led_details.jpg" alt="" id="BLOGGER_PHOTO_ID_5300373469649186562" border="0" /></a><span style="font-style: italic;">LED is connected to RB0</span><br /></div><br /><br /><span style="font-weight: bold;font-size:130%;" >Writing the software</span><br /><br />For this example, I took one of the 16f88's sample included in jallib distribution (<a href="http://code.google.com/p/jallib/source/browse/trunk/sample/by_device/16f88/16f88_pwm_led.jal">16f88_pwm_led.jal</a>), and just adapt it so it runs at 8MHz, using internal clock. It also select RB0 as the PWM pin.<br /><br />So, step by step... First, as we said, we must select which pin will carry the PWM signals...<br /><pre><br /><span style="font-weight: bold; color: rgb(51, 0, 153);">pragma target CCP1MUX RB0 -- ccp1 pin on B0</span><br /></pre><br />and configure it as output<br /><pre><br /><span style="font-weight: bold; color: rgb(51, 0, 153);">var volatile bit pin_ccp1_direction is pin_b0_direction</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);">pin_ccp1_direction = output</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);">-- (simply "pin_b0_direction = output" would do the trick too)</span><br /></pre><br />Then we include the PWM library.<br /><pre><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">include pwm_hardware</span><br /></pre><br />Few words here... This library is able to handle <span style="font-weight: bold;">up to 5 PWM channels</span> (PIC using CCP1, CCP2, CCP3, CCP4 and CCP5 registers). Using conditional compilation, it <span style="font-weight: bold;">automatically selects the appropriate underlying PWM libraries</span>, for the selected target PIC.<br /><br />Since 16f88 has only one PWM channel, it just includes "pwm_ccp1" library. If we'd used a 16f877, which has two PWM channels, it would include "pwm_ccp1" <span style="font-style: italic;">and</span> "pwm_ccp2" libraries. What is important is it's transparent to users (you).<br /><br />OK, let's continue. We now need to configure the <span style="font-weight: bold;">resolution</span>. What's the resolution ? Given a frequency, the <span style="font-weight: bold;">number of values you can have for the duty cycle</span> can vary (you could have, say, 100 different values at one frequency, and 255 at another frequency). Have a look at the datasheet for more.<br /><br />What we want here is to have the <span style="font-weight: bold;">max number of values we can for the duty cycle</span>, so we can select the exact brightness we want. We also want to <span style="font-weight: bold;">have the max frequency</span> we can have (ie. no pre-scaler).<br /><pre><br /><span style="font-weight: bold; color: rgb(51, 0, 153);">pwm_max_resolution(1)</span><br /></pre><br />If you read the<a href="http://jallib.googlecode.com/svn/trunk/doc/html/pwm_common.html"> jalapi documentation for this</a>, you'll see that the frequency will be 7.81kHz (we run at 8MHz).<br /><br />PWM channels can be turned on/off independently, now we want to activate our channel:<br /><pre><br /><span style="font-weight: bold; color: rgb(51, 0, 153);">pwm1_on()</span><br /></pre><br />Before we dive into the forever loop, I forgot to mention PWM can be used in <span style="font-weight: bold;">low or high resolution</span>. <span style="font-style: italic;">On low resolution</span>, duty cycles values range from <span style="font-style: italic;">0 to 255</span> (8 bits). <span style="font-style: italic;">On high resolution</span>, values range from <span style="font-style: italic;">0 to 1024</span> (10 bits). In this example, we'll use low resolution PWM. For high resolution, you can have a look at the other sample, <span id="crumb_links" class="ifClosed"><a href="http://code.google.com/p/jallib/source/browse/trunk/sample/by_device/16f88/16f88_pwm_led_highres.jal">16f88_pwm_led_highres.jal</a>. As you'll see, there are very few differences.<br /><br />Now let's dive into the loop...</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);"><br /><pre><br />forever loop<br /> var byte i<br /> i = 0<br /> -- loop up and down, to produce different duty cycle<br /> while i < 250 loop<br /> pwm1_set_dutycycle(i)<br /> _usec_delay(10000)<br /> i = i + 1<br /> end loop<br /> while i > 0 loop<br /> pwm1_set_dutycycle(i)<br /> _usec_delay(10000)<br /> i = i - 1<br /> end loop<br /> -- turning off, the LED lights at max.<br /> _usec_delay(500000)<br /> pwm1_off()<br /> _usec_delay(500000)<br /> pwm1_on()<br /><br />end loop<br /></pre><br /></span><br />Quite easy right ? There are <span style="font-style: italic;">two main waves</span>: one will light up the LED progressively (0 to 250), another will turn it off progressively (250 to 0). On each value, we set the duty cycle with <span style="font-weight: bold; color: rgb(51, 0, 153);">pwm1_set_dutycycle(i)</span> and wait a little so we, humans, can see the result.<br /><br />About the result, how does this look like ?<br /><br /><br /><object height="344" width="425"><param name="movie" value="http://www.youtube.com/v/r9_TfEmUSf0&hl=en&fs=1"><param name="allowFullScreen" value="true"><param name="allowscriptaccess" value="always"><embed src="http://www.youtube.com/v/r9_TfEmUSf0&hl=en&fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" height="344" width="425"></embed></object><br /><br /><br /><span style="font-weight: bold;font-size:130%;" >"I wanna try, where are the files ?"</span><br /><br />To run this sample, you'll need the <a href="http://code.google.com/p/jallib/downloads/list">last jallib pack</a> (at least 0.2 version). You'll also find the exact code we used <a href="http://jallib.googlegroups.com/web/blog_16f88_board_sl_pwm_led.jal">here</a>.<br /><br /><br /><br /><span style="font-style: italic;">Sébastien Lelong</span>Sebastien Lelonghttp://www.blogger.com/profile/00317258446230687333noreply@blogger.com10tag:blogger.com,1999:blog-8299212346186005351.post-46188642034577589892009-02-01T18:50:00.004+01:002009-02-01T19:43:11.030+01:00LicenseAs we continue to populate this blog, maybe it's time to put a license on its content. We, at jallib, want it to be as <span style="font-style: italic;">open</span> as possible, as <span style="font-style: italic;">free</span> as possible. We decided to use a <a href="http://creativecommons.org/">Creative Common</a> license.<br /><br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://creativecommons.org/licenses/by-sa/3.0/"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 88px; height: 31px;" src="http://i.creativecommons.org/l/by-sa/3.0/88x31.png" alt="" border="0" /></a><br />So, the blog's content is licensed under the <span style="font-weight: bold;">Creative Common "Attribution Share Alike"</span> license. For more information, see the <a href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Common's summary</a> and the <a href="http://creativecommons.org/licenses/by-sa/3.0/legalcode">full legal code</a>.<br /><br />Of course, this license only applies on the blog's content itself (text, photos, diagrams, schematics, videos, etc...), except when another license is explicitly used. Particularly, there are examples and code coming from jallib project, which are released under ZLIB or BSD licenses.<br /><br />In doubts, just ask on <a href="http://groups.google.com/group/jallib">jallib's group</a>.<br /><br /><br />Have fun !<br /><br /><span style="font-style: italic;">The jallib team</span>Sebastien Lelonghttp://www.blogger.com/profile/00317258446230687333noreply@blogger.com0tag:blogger.com,1999:blog-8299212346186005351.post-62925367006278483652009-01-25T11:07:00.023+01:002009-02-16T10:38:30.799+01:00Step by Step: interfacing a HD44780-compatible LCD displayIn this "Step by Step" tutorial, we're going to (hopefully) have some fun with a <span style="font-weight: bold;">LCD display</span>. Particularly one compatible with HD44780 specifications, which seem to be most widely used.<br /><br /><br /><span style="font-size:130%;"><span style="font-weight: bold;">Setting up the hardware</span></span><br /><br />As usual, there are <a href="http://www.google.com/search?hl=en&q=lcd+hd44780">plenty resources</a> on the web. I found <a href="http://home.iae.nl/users/pouweha/lcd/lcd.shtml">this one</a> quite nice, covering lots of thing. Basically, LCDs can be accessed with two distinct interfaces: <span style="font-style: italic;">4-bit or 8-bit interfaces</span>. <span style="font-style: italic;">4-bit interface requires less pins </span>(4 pins), but is somewhat slow, <span style="font-style: italic;">8-bit interface requires more pins</span> (8 pins) but is faster. <a href="http://jallib.googlecode.com/">jallib</a> comes with the two flavors, it's up to you deciding which is most important, but usually, pins are more precious than speed, particularly when using a 16F88 which only has 16 I/O pins (at best). Since 4-bit interface seems to be most used, and we'll use this one here...<br /><br />So, I've never used LCD, to be honest. Most guys consider it as an absolute minimum thing to have, since it can help a lot when debugging, by printing messages. I tend to use serial for this... Anyway, I've been given a LCD, so I can't resist anymore :)<br /><br />The LCD I have seems to be quite a nice beast ! It has 4 lines, is 20 characters long.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8D22-ibdVaBbtnk4ZQA5xS8Z4cuMHqeueWYnzRLHQdWW3ox1Cjhs7lFRubOsLmsb6sILzgOfCy7KrHwWI6YonTHfJmF1zuJk5DteRN_USFiywNF-xDXMqbSAC5x2YDBv_ZQP-4_Lpg7I/s1600-h/lcd_overview.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8D22-ibdVaBbtnk4ZQA5xS8Z4cuMHqeueWYnzRLHQdWW3ox1Cjhs7lFRubOsLmsb6sILzgOfCy7KrHwWI6YonTHfJmF1zuJk5DteRN_USFiywNF-xDXMqbSAC5x2YDBv_ZQP-4_Lpg7I/s400/lcd_overview.jpg" alt="" id="BLOGGER_PHOTO_ID_5295177998070314754" border="0" /></a><br /><br />Looking closer, "<span style="font-style: italic;">JHD 204A</span>" seems to be the reference. Near the connector, only a "1" and a "16". No pin's name.<br /><br /><div style="text-align: left;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwM1Z7RQBlQPlSbXyhEZGN0R1lYM9VkQxJ2uXDjI9t7HbTQ_5OiiuFDoG09q2SqGNEXEApJSduDAcZtII7qCaAD2yBOtlPQ80cJFryA-NK7RN9pIYmXB6_BTzs7C9R1jAGyXPEx31o5R8/s1600-h/lcd_jhd204a.jpg"><img style="margin: 0px auto 10px; display: block; cursor: pointer; width: 210px; height: 157px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwM1Z7RQBlQPlSbXyhEZGN0R1lYM9VkQxJ2uXDjI9t7HbTQ_5OiiuFDoG09q2SqGNEXEApJSduDAcZtII7qCaAD2yBOtlPQ80cJFryA-NK7RN9pIYmXB6_BTzs7C9R1jAGyXPEx31o5R8/s400/lcd_jhd204a.jpg" alt="" id="BLOGGER_PHOTO_ID_5295177999941603890" border="0" /></a><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQEDQXNUA-QiVsE9ymaZNGKrAdo9k2V_gIneINO2hzNLA3KzEE2ppXsuvApSvvyv3aq02x507ZzNb-o_9TWOr83kRacdJtv0VXwXDjz6aKA3F9tlTOyUk16Vwd4MM-kMtRfpmWVOGZdwQ/s1600-h/lcd_1.jpg"><img style="margin: 0px auto 10px; display: block; cursor: pointer; width: 209px; height: 155px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQEDQXNUA-QiVsE9ymaZNGKrAdo9k2V_gIneINO2hzNLA3KzEE2ppXsuvApSvvyv3aq02x507ZzNb-o_9TWOr83kRacdJtv0VXwXDjz6aKA3F9tlTOyUk16Vwd4MM-kMtRfpmWVOGZdwQ/s400/lcd_1.jpg" alt="" id="BLOGGER_PHOTO_ID_5295177992984217746" border="0" /></a></div><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHwucYnJV1TQ9fhEgWT4oSnXMKMVQCkmAgGuFjxOMUXPuvHHq5b0rrwBHD1LMZ03G2Kk4177WdIDJpCtv9tSnDlFZvTQkqJfaP7CsuQux8HMy8M0fRqHqOByzDgwBr8bDA48gTyJy4jeA/s1600-h/lcd_16.jpg"><img style="margin: 0px auto 10px; display: block; cursor: pointer; width: 210px; height: 156px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHwucYnJV1TQ9fhEgWT4oSnXMKMVQCkmAgGuFjxOMUXPuvHHq5b0rrwBHD1LMZ03G2Kk4177WdIDJpCtv9tSnDlFZvTQkqJfaP7CsuQux8HMy8M0fRqHqOByzDgwBr8bDA48gTyJy4jeA/s400/lcd_16.jpg" alt="" id="BLOGGER_PHOTO_ID_5295177995142905778" border="0" /></a><br />Googling the whole points to a forum, and at least a link to the <a href="http://www.8051projects.net/e107_files/public/1231066792_13674_FT0_jm204aspec.pdf">datasheet</a>. A section describes the "Pin Assignement". Now I'm sure about how to connect this LCD.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcVcSfy0qLYyApfsHVdEHUtwaKHHPpy9l7r4TAHSh6-zsWqgmhtW5LwPJvIyB5XKneTI4AJBmBgRG8f3Bt8EJyK4ODKzpQiSDISKyhBzT8_OdrC94e0Q1tPKz4hkGdqObWkFW2w2dYdhI/s1600-h/lcd_pins.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 296px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcVcSfy0qLYyApfsHVdEHUtwaKHHPpy9l7r4TAHSh6-zsWqgmhtW5LwPJvIyB5XKneTI4AJBmBgRG8f3Bt8EJyK4ODKzpQiSDISKyhBzT8_OdrC94e0Q1tPKz4hkGdqObWkFW2w2dYdhI/s400/lcd_pins.png" alt="" id="BLOGGER_PHOTO_ID_5295184198708392402" border="0" /></a><br />For this tutorial, we're going to keep it simple:<br /><ul><li>as previously said, we'll use 4-bit interface. This means we'll use DB4, DB5, DB6 and DB7 pins (respectively pin 11, 12, 13 and 14).<br /></li><li>we won't read from LCD, so R/W pin must be grounded (pin 5)<br /></li><li>we won't use contrast as well, V5 pin (or Vee) must be grounded (pin 3)</li></ul>Including pins for power, we'll use 10 pins out of the 16 available, 6 being connected to the PIC (RS, EN and 4 data lines).<br /><br />For convenience, I soldered a male connector on the LCD. This will help when building the whole on a breadboard.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDmClSAA0UVsPKHqKUyphraJjny5Z_SHZXXJduPueB8B7w3BZgfKkQEpxk0Nn2u52f2Lawyr96AX0F9FJlP80dOcwcq8yZHd31dagPJOhjmyxcaq0L1WjmoMxdp9_-yGL0TAoyUUxdViI/s1600-h/lcd_connector.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 240px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDmClSAA0UVsPKHqKUyphraJjny5Z_SHZXXJduPueB8B7w3BZgfKkQEpxk0Nn2u52f2Lawyr96AX0F9FJlP80dOcwcq8yZHd31dagPJOhjmyxcaq0L1WjmoMxdp9_-yGL0TAoyUUxdViI/s400/lcd_connector.jpg" alt="" id="BLOGGER_PHOTO_ID_5295177993128041266" border="0" /></a><br /><br />So we now have everything to build the circuit. Here's the schematic. It also includes a LED, it will help us checking everything is ok while powering up the board.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkuD_j55oDA6caF-k66GqUsrmDeh2YeCIZLKje7hjbFbm_MLlrzTgBi6F7aIFneMbxGjBk8jq01b3cOvDwufqxl-YlsnYws8SeGeUOcF0HcTj9Vxc5z2zRr3-xBzuO9R6JrpKUPTTs8qU/s1600-h/lcd_4bit.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 338px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkuD_j55oDA6caF-k66GqUsrmDeh2YeCIZLKje7hjbFbm_MLlrzTgBi6F7aIFneMbxGjBk8jq01b3cOvDwufqxl-YlsnYws8SeGeUOcF0HcTj9Vxc5z2zRr3-xBzuO9R6JrpKUPTTs8qU/s400/lcd_4bit.png" alt="" id="BLOGGER_PHOTO_ID_5295187726115451922" border="0" /></a><br /><br />Using a breadboard, it looks like this:<br /><br /><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRdgNRGSWtHGqRKoYRzWVjxnST-UciVg1Hpfauxwd8MoJ7HEQr0B9Aqyt_ohyphenhyphenOxpgCZDgH_gG8gI_S9iqrWvX5pDQiL-w3bGgx2MLEjpjsgNC3WVgIICVUniarbQoGxcc9UqC2PAlPf1s/s1600-h/lcd_bwhole.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRdgNRGSWtHGqRKoYRzWVjxnST-UciVg1Hpfauxwd8MoJ7HEQr0B9Aqyt_ohyphenhyphenOxpgCZDgH_gG8gI_S9iqrWvX5pDQiL-w3bGgx2MLEjpjsgNC3WVgIICVUniarbQoGxcc9UqC2PAlPf1s/s400/lcd_bwhole.jpg" alt="" id="BLOGGER_PHOTO_ID_5295189279434178466" border="0" /></a><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHanhSIbzKqovilZARt90aMPZ3VyElaCx_DH8n-I8XfFGqTDIgf3nsbHrvqrHFmf352WTUXpzrsr56f8m_QdoFFWQ4MRLkqjfmTMy-S09JY-cNqEw7uLySpu0tv1xys86bPJDFz6jr4Vo/s1600-h/lcd_bpic.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 300px; height: 400px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHanhSIbzKqovilZARt90aMPZ3VyElaCx_DH8n-I8XfFGqTDIgf3nsbHrvqrHFmf352WTUXpzrsr56f8m_QdoFFWQ4MRLkqjfmTMy-S09JY-cNqEw7uLySpu0tv1xys86bPJDFz6jr4Vo/s400/lcd_bpic.jpg" alt="" id="BLOGGER_PHOTO_ID_5295189280896868962" border="0" /></a><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBkbHSngyxM7iPAnBr_qb5Z2YF075Kqsv7kvIb2KQ5p4M0yF3LiuqD8u7leg8AOZim_s3KLHAeWJuvYtbS7FCtJVGCzuhqG4u6dDPvOpQBtRe5g1IhfOVZhYbIGzWjxTbYuA9Xw40t_uc/s1600-h/lcd_bconn.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBkbHSngyxM7iPAnBr_qb5Z2YF075Kqsv7kvIb2KQ5p4M0yF3LiuqD8u7leg8AOZim_s3KLHAeWJuvYtbS7FCtJVGCzuhqG4u6dDPvOpQBtRe5g1IhfOVZhYbIGzWjxTbYuA9Xw40t_uc/s400/lcd_bconn.jpg" alt="" id="BLOGGER_PHOTO_ID_5295189282782076466" border="0" /></a><br /><br /><div style="text-align: left;"><span style="font-size:130%;"><span style="font-weight: bold;">Writing the software</span></span></div><br /><div style="text-align: left;">For this tutorial, we'll use one of the available samples from <a href="http://code.google.com/p/jallib/source/browse/">jallib repository</a>. I took <a href="http://code.google.com/p/jallib/source/browse/trunk/sample/by_device/16f88/16f88_lcd_hd44780_4.jal">one</a> for 16f88, and adapt it to my board (specifically, I wanted to use PORTA when connecting the LCD, and let PORTB's pins as is).<br /><br />As usual, writing a program with jallib starts with configuring and declaring some parameters. So we first have to declare which pins will be connected:<br /><pre><br /><span style="color: rgb(51, 0, 153); font-weight: bold;"> -- LCD IO definition</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">var bit lcd_rs is pin_a6 -- LCD command/data select.</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">var bit lcd_rs_direction is pin_a6_direction</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">var bit lcd_en is pin_a7 -- LCD data trigger</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">var bit lcd_en_direction is pin_a7_direction</span><br /><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">var byte lcd_dataport is porta_low -- LCD data port</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">var byte lcd_dataport_direction is porta_low_direction<br /><br />-- set direction<br />lcd_rs_direction = output<br />lcd_en_direction = output<br />lcd_dataport_direction = output<br /></span></pre><br />This is, pin by pin, the translation of the schematics. Maybe except <span style="font-weight: bold; color: rgb(0, 0, 102);">porta_low</span>. This represents pin A0 to A3, that is pins for our 4 lines interface. <span style="color: rgb(0, 0, 102); font-weight: bold;">porta_high </span>represents pin A4 to A7, and <span style="color: rgb(0, 0, 102); font-weight: bold;">porta</span> reprensents the whole port, A0 to A7. These are just "shorcuts".<br /><br />We also have to declare the <span style="font-weight: bold;">LCD geometry</span>:<br /><pre><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">const byte LCD_ROWS = 4 -- 4 lines</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">const byte LCD_CHARS = 20 -- 20 chars per line</span><br /></pre><br />Once declared, we can then include the library and initialize it:<br /><br /><pre><span style="color: rgb(51, 0, 153); font-weight: bold;">include lcd_hd44780_4 -- LCD library with 4 data lines<br />lcd_init() -- initialize LCD<br /></span></pre><br />For this example, we'll also use the <span style="font-weight: bold; color: rgb(0, 0, 102);">print.jal</span> library, which provides nice helpers when printing variables.<br /><br /><pre><span><span style="color: rgb(51, 0, 153); font-weight: bold;">include print</span></span></pre><br />Now the main part... How to write things on the LCD.<br /><br /><ul><li>You can either use a procedure call: <span style="font-weight: bold; color: rgb(0, 0, 102);">lcd_writechar("a")</span></li><li>or you can use the pseudo-variable<span style="font-weight: bold; color: rgb(0, 0, 102);"></span><span style="color: rgb(0, 0, 102);"><span style="color: rgb(0, 0, 0);"> : </span></span><span style="font-weight: bold; color: rgb(0, 0, 102);">lcd = "a"</span></li><li><span style="color: rgb(0, 0, 102); font-weight: bold;">lcd_setcursor(x,y)</span> will set the cursor position. x is the line, y is the row, starting from 0</li><li><span style="color: rgb(0, 0, 0);">finally, </span><span style="font-weight: bold; color: rgb(0, 0, 102);">lcd_clearscreen()</span> will, well... clear the screen !<br /></li></ul> <a href="http://jallib.googlecode.com/svn/trunk/doc/html/lcd_hd44780_4.html">Full API documentation</a> is available on <a href="http://jallib.googlecode.com/svn/trunk/doc/html/index.html">jalapi</a>.<br /><br />So, for this example, we'll write some chars on each line, and print an increasing (and incredible) counter:<br /><pre><br /><span style="font-weight: bold; color: rgb(51, 0, 153);">const byte str1[] = "Hello world!" -- define strings</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);">const byte str2[] = "third line"</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);">const byte str3[] = "fourth line"<br /><br /></span><span style="font-weight: bold; color: rgb(51, 0, 153);">print_string(lcd, str1) -- show hello world!</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);">lcd_setcursor(2,0) -- to 3rd line</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);">print_string(lcd, str2)</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);">lcd_setcursor(3,0) -- to 4th line</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);">print_string(lcd, str3)</span><br /><br /><span style="font-weight: bold; color: rgb(51, 0, 153);">var byte counter = 0</span><br /><br /><span style="font-weight: bold; color: rgb(51, 0, 153);">forever loop -- loop forever</span><br /><br /><span style="font-weight: bold; color: rgb(51, 0, 153);"> counter = counter + 1 -- update counter</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);"> lcd_setcursor(1,0) -- second line</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);"> print_byte_hex(lcd, counter) -- output in hex format</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);"> delay_100ms(3) -- wait a little</span><br /><br /><span style="font-weight: bold; color: rgb(51, 0, 153);"> if counter == 255 then -- counter wrap</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);"> lcd_setcursor(1,1) -- 2nd line, 2nd char</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);"> lcd = " " -- clear 2nd char</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);"> lcd = " " -- clear 3rd char</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);"> end if</span><br /><br /><span style="font-weight: bold; color: rgb(51, 0, 153);">end loop</span><br /></pre><br /><br />The full and ready-to-compile code is available on jallib group's file section:<br /><ul><li><a href="http://groups.google.com/group/jallib/web/blog_16f88_sl_lcd_hd44780_4.jal">blog_16f88_sl_lcd_hd44780_4.jal</a><br /></li></ul><br />You'll need last jallib-pack, available on <a href="http://code.google.com/p/jallib/downloads/list">jallib's download section</a>.<br /><br /><br /><br /><span style="font-size:130%;"><span style="font-weight: bold;">How does this look when running ?</span></span><br /><br />Here's the video !<br /><br /><br /><object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/hIVMuaz8OS8&hl=en&fs=1"><param name="allowFullScreen" value="true"><param name="allowscriptaccess" value="always"><embed src="http://www.youtube.com/v/hIVMuaz8OS8&hl=en&fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object><br /><br /><br /><br /><span style="font-style: italic;">Sébastien Lelong<br /></span></div></div>Sebastien Lelonghttp://www.blogger.com/profile/00317258446230687333noreply@blogger.com9tag:blogger.com,1999:blog-8299212346186005351.post-73147531141067204172009-01-20T21:41:00.028+01:002009-01-30T23:46:06.188+01:00Step by Step: building an i2c slave with jallib (part 3)<span style="font-size:130%;"><span style="font-style: italic; font-weight: bold;">Part 3 : implementing an i2c slave ISR<br /></span></span><br /><br />In previous parts of this tutorial, we've seen <a href="http://jallib.blogspot.com/2009/01/step-by-step-building-i2c-slave-with.html">a little of theory</a>, we've also seen how to <a href="http://jallib.blogspot.com/2009/01/step-by-step-building-i2c-slave-with_17.html">check if the i2c bus is operational</a>, now the time has come to finally build our i2c slave. But what will slave will do ? For this example, slave is going to do something amazing: it'll echo received chars. Oh, I'm thinking about something more exciting: it will "almost" echo chars:<br /><ul><li>if you send "a", it sends "b"</li><li>if you send "b", it sends "c",<br /></li><li>if you send "z", it sends "{"</li><li>...</li></ul>(why "{" ? According to ASCII, "z" is the character for position 122. 123 is... "{")<br /><br /><br /><span style="font-size:130%;"><span style="font-weight: bold;">Building the i2c master</span></span><br /><br />Let's start with the easy part. What will master do ? Just collect characters from a serial link, and convert them to i2c commands. So you'll need a PIC to which you can send data via serial. I mean you'll need a board with serial com. capabilities. I mean we won't do this on a breadboard... There are plenty out there on the Internet, pick your choice. If you're interested, you can <a href="http://sirbot.org/sirbot-modules/main_board/">find one</a> on my <a href="http://sirbot.org/">SirBot</a> site: dedicated to 16f88, serial com. available, and i2c ready (pull-ups resistors).<br /><br />It looks like this:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://sirbot.org/sirbot-modules/main_board/mainboard_up.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 317px; height: 237px;" src="http://sirbot.org/sirbot-modules/main_board/mainboard_up.jpg" alt="" border="0" /></a><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://sirbot.org/sirbot-modules/main_board/mainboard_facade.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 319px; height: 237px;" src="http://sirbot.org/sirbot-modules/main_board/mainboard_facade.jpg" alt="" border="0" /></a><br />Two connectors are used for earch port, <span style="font-style: italic;">PORTA</span> and <span style="font-style: italic;">PORTB</span>, to plug daughter boards, or a breadboard in our case.<br /><br />We'll use a <span style="font-style: italic;">16f88 as a i2c master</span>. 16f88 only own a SSP module, not MSSP, this means it can't handle i2c in hardware (no built-in i2c master). Not a problem, we'll use i2c software library.<br /><br />The i2c initialization part is quite straight forward. SCL and SDA pins are declared, we'll use a standard speed, 400KHz,<br /><br /><pre><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">-- I2C io definition</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">var volatile bit i2c_scl is pin_b4</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">var volatile bit i2c_scl_direction is pin_b4_direction</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">var volatile bit i2c_sda is pin_b1</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">var volatile bit i2c_sda_direction is pin_b1_direction</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">-- i2c setup</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">const word _i2c_bus_speed = 4 ; 400kHz</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">const bit _i2c_level = true ; i2c levels (not SMB)</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">include i2c_software</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">i2c_initialize()</span><br /></pre><br />We'll also use the level 1 i2c library. The principle is easy: you declare two buffers, one for receiving and one for sending bytes, and then you call procedure specifying how many bytes you want to send, and how many are expected to be returned. Joep has written <a href="http://jallib.blogspot.com/2008/12/i2c-master.html">a nice post about this</a>, if you want to read more about this. We'll send one byte at a time, and receive one byte at a time, so buffers should be one byte long.<br /><pre><span style="color: rgb(51, 0, 153); font-weight: bold;">const single_byte_tx_buffer = 1 -- only needed when length is 1</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">var byte i2c_tx_buffer[1]</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">var byte i2c_rx_buffer[1]</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">include i2c_level1</span><br /></pre><br />What's next ? Well, master also has to read chars from a serial line. Again, easy:<br /><pre><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">const usart_hw_serial = true</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">const serial_hw_baudrate = 57_600</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">include serial_hardware</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">serial_hw_init()</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">-- Tell the world we're ready !</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">serial_hw_write("!")</span><br /></pre><br />So when the master is up, it should <span style="font-style: italic;">at least</span> send the "!" char.<br /><br /><br />Then we need to specify the slave's address. This is a 8-bits long address, the 8th bits being the bit specifying if operation is a <span style="font-style: italic;">read </span>or <span style="font-style: italic;">write</span> one (see <a href="http://jallib.blogspot.com/2009/01/step-by-step-building-i2c-slave-with.html">part 1</a> for more). We then need to collect those chars coming from the PC and sends them to the slave.<br /><br />The following should do the trick (believe me, it does :))<br /><br /><pre><br /><span style="font-weight: bold; color: rgb(51, 0, 153);">var byte icaddress = 0x5C -- slave address</span><br /><br /><span style="font-weight: bold; color: rgb(51, 0, 153);">forever loop</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);"> if serial_hw_read(pc_char)</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);"> then</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);"> serial_hw_write(pc_char) -- echo</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);"> -- transmit to slave</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);"> -- we want to send 1 byte, and receive 1 from the slave</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);"> i2c_tx_buffer[0] = pc_char</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);"> var bit _trash = i2c_send_receive(icaddress, 1, 1)</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);"> -- receive buffer should contain our result</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);"> ic_char = i2c_rx_buffer[0]</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);"> serial_hw_write(ic_char)</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);"> end if</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);">end loop</span><br /></pre><br /><br />The whole program is available on jallib SVN repository <a href="http://jallib.googlecode.com/svn/trunk/sample/by_device/16f88/16f88_i2c_sw_master_echo.jal">here</a> (subject to change, since not released yet).<br /><br /><br /><span style="font-size:130%;"><span style="font-weight: bold;">Building the i2c slave</span></span><br /><br />So this is the main part ! As exposed on <a href="http://jallib.blogspot.com/2009/01/step-by-step-building-i2c-slave-with.html">first post</a>, we're going to implement a <span style="font-style: italic;">finite state machine</span>. jallib comes with a library where all the logic is already coded, in a ISR. You just have to define what to do for each state encountered during the program execution. To do this, we'll have to <span style="font-weight: bold;">define several callbacks</span>, that is procedures that will be called on appropriate state.<br /><br />Before this, we need to <span style="font-weight: bold;">setup and initialize our slave</span>. i2c address should <span style="font-style: italic;">exactly</span> be the same as the one defined in the master section. This time, we won't use interrrupts on Start/Stop signals; we'll just let the SSP module triggers an interrupts when the i2c address is recognized (no interrupts means address issue, or hardware problems, or...). Finally, since slave is expected to receive a char, and send char + 1, we need a global variable to store the results. This gives:<br /><pre><br /><span style="font-weight: bold; color: rgb(0, 0, 153);">include i2c_hw_slave<br /><br /></span><span style="font-weight: bold; color: rgb(0, 0, 153);"></span><span style="font-weight: bold; color: rgb(0, 0, 153);"></span><span style="font-weight: bold; color: rgb(0, 0, 153);">const byte SLAVE_ADDRESS = 0x5C</span><br /><span style="font-weight: bold; color: rgb(0, 0, 153);">i2c_hw_slave_init(SLAVE_ADDRESS)</span><br /><br /><span style="font-weight: bold; color: rgb(0, 0, 153);">-- will store what to send back to master</span><br /><span style="font-weight: bold; color: rgb(0, 0, 153);">-- so if we get "a", we need to store "a" + 1</span><br /><span style="font-weight: bold; color: rgb(0, 0, 153);">var byte data</span><br /></pre><br />Before this, let's try to understand how master will talk to the slave (<span style="color: rgb(204, 0, 0);">red</span>) and what the slave should do (<span style="color: rgb(0, 102, 0);">green</span>), according to each state (with code following):<br /><ul><li><span style="font-weight: bold;">state 1</span>: <span style="color: rgb(204, 0, 0);">master initiates a write operation</span> (but does not send data yet). Since no data is sent, <span style="color: rgb(0, 153, 0);">slave should just do... nothing</span> (slave just knows someone wants to send data).<br /></li></ul><pre><span style="font-weight: bold; color: rgb(51, 0, 153);"></span><span style="font-weight: bold; color: rgb(51, 0, 153);">procedure i2c_hw_slave_on_state_1(byte in _trash) is</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);"> pragma inline</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);"> -- _trash is read from master, but it's a dummy data</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);"> -- usually (always ?) ignored</span><br /><span style="font-weight: bold; color: rgb(51, 0, 153);">end procedure<br /><br /></span></pre><ul><li><span style="font-weight: bold;">state 2</span>: <span style="color: rgb(204, 0, 0);">master actually sends data, that is one character</span>. <span style="color: rgb(0, 153, 0);">Slave should get this char, and process it (char + 1) for further sending</span>.<br /></li></ul><pre><span style="font-weight: bold; color: rgb(0, 0, 153);"></span><span style="font-weight: bold; color: rgb(0, 0, 153);">procedure i2c_hw_slave_on_state_2(byte in rcv) is</span><br /><span style="font-weight: bold; color: rgb(0, 0, 153);"> pragma inline</span><br /><span style="font-weight: bold; color: rgb(0, 0, 153);"> -- ultimate data processing... :)</span><br /><span style="font-weight: bold; color: rgb(0, 0, 153);"> data = rcv + 1</span><br /><span style="font-weight: bold; color: rgb(0, 0, 153);">end procedur<span style="font-family:monospace;">e<br /><br /></span></span></pre><ul><li><span style="font-weight: bold;">state 3</span>: <span style="color: rgb(204, 0, 0);">master initiates a read operation, it wants to get the echo back</span>. <span style="color: rgb(0, 153, 0);">Slave should send its processed char</span>.</li></ul><pre><span style="color: rgb(0, 0, 153); font-weight: bold;">procedure i2c_hw_slave_on_state_3() is</span><br /><span style="color: rgb(0, 0, 153); font-weight: bold;"> pragma inline</span><br /><span style="color: rgb(0, 0, 153); font-weight: bold;"> i2c_hw_slave_write_i2c(data)</span><br /><span style="color: rgb(0, 0, 153); font-weight: bold;">end procedure</span><br /><br /></pre><ul><li><span style="font-weight: bold;">state 4</span>: <span style="color: rgb(204, 0, 0);">master still wants to read some information</span>. This should never occur, since one char is sent and read at a time. <span style="color: rgb(0, 153, 0);">Slave should thus produce an error</span>.<br /></li></ul><pre><span style="font-weight: bold; color: rgb(0, 0, 153);">procedure i2c_hw_slave_on_state_4() is</span><br /><span style="font-weight: bold; color: rgb(0, 0, 153);"> pragma inline</span><br /><span style="font-weight: bold; color: rgb(0, 0, 153);"> -- This shouldn't occur in our i2c echo example</span><br /><span style="font-weight: bold; color: rgb(0, 0, 153);"> i2c_hw_slave_on_error()</span><br /><span style="font-weight: bold; color: rgb(0, 0, 153);">end procedure</span><br /><br /></pre><ul><li><span style="font-weight: bold;">state 5</span>: <span style="color: rgb(204, 0, 0);">master hangs up the connection</span>. <span style="color: rgb(0, 153, 0);">Slave should reset its state.</span><br /></li></ul><pre><span style="color: rgb(0, 0, 153); font-weight: bold;">procedure i2c_hw_slave_on_state_5() is</span><br /><span style="color: rgb(0, 0, 153); font-weight: bold;"> pragma inline</span><br /><span style="color: rgb(0, 0, 153); font-weight: bold;"> data = 0</span><br /><span style="color: rgb(0, 0, 153); font-weight: bold;">end procedure</span><br /></pre><br />Finally, we need to define a callback in case of error. You could do anything, like resetting the PIC, and sending log/debug data, etc... In our example, we'll blink forever:<br /><br /><pre><span style="font-weight: bold; color: rgb(0, 0, 153);">procedure i2c_hw_slave_on_error() is</span><br /><span style="font-weight: bold; color: rgb(0, 0, 153);"> pragma inline</span><br /><span style="font-weight: bold; color: rgb(0, 0, 153);"> -- Just tell user user something's got wrong</span><br /><span style="font-weight: bold; color: rgb(0, 0, 153);"> forever loop</span><br /><span style="font-weight: bold; color: rgb(0, 0, 153);"> led = on</span><br /><span style="font-weight: bold; color: rgb(0, 0, 153);"> _usec_delay(200000)</span><br /><span style="font-weight: bold; color: rgb(0, 0, 153);"> led = off</span><br /><span style="font-weight: bold; color: rgb(0, 0, 153);"> _usec_delay(200000)</span><br /><span style="font-weight: bold; color: rgb(0, 0, 153);"> end loop</span><br /><span style="font-weight: bold; color: rgb(0, 0, 153);">end procedure</span><br /></pre><br />Once callbacks are defined, we can include the famous ISR library.<br /><pre><span style="font-weight: bold; color: rgb(0, 0, 153);">include i2c_hw_slave_isr</span><br /></pre><br />So the sequence is:<br /><ol><li><span style="font-weight: bold;">include i2c_hw_slave</span>, and setup your slave</li><li><span style="font-weight: bold;">define your callbacks</span>,</li><li><span style="font-weight: bold;">include the ISR</span><br /></li></ol><br /><br />The full code is available from jallib's SVN repository (caution, not released yet, could be modified):<br /><br /><ul><li><a href="http://jallib.googlecode.com/svn/trunk/include/peripheral/i2c/i2c_hw_slave.jal">i2c_hw_slave.jal</a></li><li><a href="http://jallib.googlecode.com/svn/trunk/include/peripheral/i2c/i2c_hw_slave_isr.jal">i2c_hw_slave_isr.jal</a></li><li><a href="http://jallib.googlecode.com/svn/trunk/sample/by_device/16f88/16f88_i2c_sw_master_echo.jal">16f88_i2c_sw_master_echo.jal</a></li><li><a href="http://jallib.googlecode.com/svn/trunk/sample/by_device/16f88/16f88_i2c_hw_slave_echo.jal">16f88_i2c_hw_slave_echo.jal</a><br /></li></ul><br />You'll also need jallib-pack from <a href="http://code.google.com/p/jallib/downloads/list">here</a>. Copy the two libraries to the "lib" directory, compile the two samples and program two 16f88.<br /><br />(Edit on 01/30: libraries and samples are now include in jallib's version > 0.1, no extra download needed !)<br /><br /><span style="font-size:130%;"><span style="font-weight: bold;">Connecting and testing the whole thing...</span></span><br /><br />As previously said, the board I use is ready to be used with a serial link. It's also i2c ready, I've put the two pull-ups resistors. If your board doesn't have those resistors, you'll have to add them on the breadboard, or it won't work (read <a href="http://jallib.blogspot.com/2009/01/step-by-step-building-i2c-slave-with_17.html">part 2</a> to know and see why...).<br /><br />I use a connector adapted with a PCB to connect my main board with my breadboard. Connector's wires provide power supply, 5V-regulated, so no other powered wires it required.<br /><br /><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhV6lN9SEl04_XzrqY-kYlkMhv9GaE0p1IJLp5hRtkBehL2666Nbm4YS9yVRzu1E3a4v04tlplfueenYJJnsM8h70XjBIkhI3iLS5pnWG2XcZ-l2ZI4GuUHZa01JenUdL90Bz6MrzC5xsI/s1600-h/connector.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhV6lN9SEl04_XzrqY-kYlkMhv9GaE0p1IJLp5hRtkBehL2666Nbm4YS9yVRzu1E3a4v04tlplfueenYJJnsM8h70XjBIkhI3iLS5pnWG2XcZ-l2ZI4GuUHZa01JenUdL90Bz6MrzC5xsI/s400/connector.jpg" alt="" id="BLOGGER_PHOTO_ID_5294211722016368658" border="0" /></a><span style="font-style: italic;">Connector, with power wires<br /></span></div><br /><br /><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguR71mpagmPh3yrgLoUT093xWwcWd4Wca1WqMouIhLZPJuMPGULn6UVXO2MA_Zn-tHsVTrTYVa5JdVZj-q1UwNw-8VAG6nOSFSbP2ftdY0HCwHbXPIvQ6NENerKXlCb9KIALmEkgSEDNk/s1600-h/details.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguR71mpagmPh3yrgLoUT093xWwcWd4Wca1WqMouIhLZPJuMPGULn6UVXO2MA_Zn-tHsVTrTYVa5JdVZj-q1UwNw-8VAG6nOSFSbP2ftdY0HCwHbXPIvQ6NENerKXlCb9KIALmEkgSEDNk/s400/details.jpg" alt="" id="BLOGGER_PHOTO_ID_5294211738507118690" border="0" /></a><span style="font-style: italic;">Everything is ready...</span><br /></div><br /><br /><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUgQFmEpJpxphmb7Q6xX_ziKi6IUFKg8gzDKEsCJ-gemy60Dab1RvedkKPl7UjQcsfHWIOcem8k9erii8vV5ro_dqEY3oBDHu9JU2GCGi1eEdeCi2k7NBNWfjHDOGC6zvK542y6yu2Ipk/s1600-h/crimescene.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUgQFmEpJpxphmb7Q6xX_ziKi6IUFKg8gzDKEsCJ-gemy60Dab1RvedkKPl7UjQcsfHWIOcem8k9erii8vV5ro_dqEY3oBDHu9JU2GCGi1eEdeCi2k7NBNWfjHDOGC6zvK542y6yu2Ipk/s400/crimescene.jpg" alt="" id="BLOGGER_PHOTO_ID_5294211728747431810" border="0" /></a><span style="font-style: italic;">Crime scene: main board, breadboard </span><br /><span style="font-style: italic;">and battery pack</span><br /></div><br /><br />Once connected, power the whole and use a terminal to test it. When pressing "a", you'll get a "a" as an echo from the master, then "b" as result from the slave.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBrYNmrmtZyZm1-XppLXxyN9To5l8bW101W38tbYOtGjs9jzxpRcU0nY2sdvSXwAWtEssPbKUVwu2s-qZyBFMi7K1_CU7yqtoEfVCFiPPl6hNRYocku73TApyVkE7CBWBuaBabquyAchA/s1600-h/pseudoecho.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 77px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBrYNmrmtZyZm1-XppLXxyN9To5l8bW101W38tbYOtGjs9jzxpRcU0nY2sdvSXwAWtEssPbKUVwu2s-qZyBFMi7K1_CU7yqtoEfVCFiPPl6hNRYocku73TApyVkE7CBWBuaBabquyAchA/s400/pseudoecho.png" alt="" id="BLOGGER_PHOTO_ID_5294211739738330594" border="0" /></a><br /><br /><span style="font-weight: bold;">What now ?</span><span style="font-size:130%;"><span style="font-weight: bold;"></span></span><br /><br />We've seen how to implement a simple i2c hardware slave. The ISR library provides all the logic about the finite state machine. <span style="font-style: italic;">You just have to define callbacks, according to your need</span>.<br /><br />i2c is a widely used protocol. Most of the time, you access i2c devices, acting as a master. We've seen how to be on the other side, on the slave side. Being on the slave side means you can build modular boards, accessible with a standard protocol. For instance, I've build a <a href="http://sirbot.org/sirbot-modules/dc-motor-controller-board">DC motor controller daughter board</a> using this. It's a module, a unit on its own, just plug, and send/receive data, with just two wires.<br /><br />And I also plan to build a LCD controller board, but that's for another "Step by Step" post :)<br /><br /><br />Reading:<br /><br /><ul><li><a href="http://jallib.blogspot.com/2009/01/step-by-step-building-i2c-slave-with.html">Part 1: a few words before getting our hands dirty...</a></li><li><a href="http://jallib.blogspot.com/2009/01/step-by-step-building-i2c-slave-with_17.html">Part 2: checking the hardware and the i2c bus...</a></li><li>Part 3: implementing an i2c slave ISR</li></ul><br /><br /><br /><span style="font-style: italic;">Sébastien Lelong</span>Sebastien Lelonghttp://www.blogger.com/profile/00317258446230687333noreply@blogger.com0tag:blogger.com,1999:blog-8299212346186005351.post-3340648331356061092009-01-17T20:59:00.030+01:002009-01-30T23:43:38.083+01:00Step by Step: building an i2c slave with jallib (part 2)<span style="font-size:130%;"><span style="font-style: italic; font-weight: bold;">Part 2 : checking the hardware and the i2c bus...<br /></span></span><br /><br /><a href="http://jallib.blogspot.com/2009/01/step-by-step-building-i2c-slave-with.html">Last time</a>, we saw a basic overview of how to implement an i2c slave, using a finite state machine implementation. Today, we're going to get our hands a little dirty, and starts connecting our master/slave together.<br /><br />First of all, i2c is quite hard to debug, especially if you don't own an oscilloscope (like me). So you have to be accurate and rigorous. That's why, in this second part of this tutorial, we're going to setup the hardware, and just make sure the i2c bus is properly operational.<br /><br />Connecting two PIC together through i2c is quite easy from a hardware point of view. Just connect SDA and SCL together, and <span style="font-weight: bold;">don't forget pull-ups resistors</span>. There are many differents values for these resistors, depending on <span style="font-style: italic;">how long the bus is</span>, or <span style="font-style: italic;">the speed you want to reach</span>. Most people use 2.2K resistors, so let's do the same ! The following schematics is here to help:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNbaC1t_zWRCu5OdfBCCuhnQvgsecOoBgcbamCRUow4zFhM2-LaHUZfHz6shkTyEySoM9w2Q2U2NwS6iVQArP_prpkoY-0SWNQpHSqyx1i-VxT3Xwf0XnEu9Z0fytTuo_HvlUtVvR2SZE/s1600-h/i2c_check_bus_schematic.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 202px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNbaC1t_zWRCu5OdfBCCuhnQvgsecOoBgcbamCRUow4zFhM2-LaHUZfHz6shkTyEySoM9w2Q2U2NwS6iVQArP_prpkoY-0SWNQpHSqyx1i-VxT3Xwf0XnEu9Z0fytTuo_HvlUtVvR2SZE/s400/i2c_check_bus_schematic.png" alt="" id="BLOGGER_PHOTO_ID_5292356850686455746" border="0" /></a><br />In this circuit, both PIC have a LED connected, which will help us understand what's going on. On a breadboard, this looks like that:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwYb51HXEPigHOHvu2kw8YElhXuSOHI8IIH0o4RPosX4PySygs2Y-ZUs_X-kTYY5JyxnGO0MutVf8mRZZzA3bDTWwbAy-jd-7P5Y6n5dK-uFITFoBX-oo0mXUVydNrbCMCTSNpp3tabkY/s1600-h/breadboard_top.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwYb51HXEPigHOHvu2kw8YElhXuSOHI8IIH0o4RPosX4PySygs2Y-ZUs_X-kTYY5JyxnGO0MutVf8mRZZzA3bDTWwbAy-jd-7P5Y6n5dK-uFITFoBX-oo0mXUVydNrbCMCTSNpp3tabkY/s400/breadboard_top.jpg" alt="" id="BLOGGER_PHOTO_ID_5292363034511689570" border="0" /></a><br />The master is on the right side, the slave on the left. I've put the two pull-ups resistors near the master:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFFelBbWJceHV6Y3UwugWZexZv7bRlRRLvPW3Y9wzsAP28YD9NUO_DXdKCIUcRrQ_MurvpMQS4lh3ygTl2-UpDxEN_bt5LjT5t1WU5OxnKlpmYb_RDFIhqurTWWd4-MZN09Ar-pZgQo5o/s1600-h/pullups.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFFelBbWJceHV6Y3UwugWZexZv7bRlRRLvPW3Y9wzsAP28YD9NUO_DXdKCIUcRrQ_MurvpMQS4lh3ygTl2-UpDxEN_bt5LjT5t1WU5OxnKlpmYb_RDFIhqurTWWd4-MZN09Ar-pZgQo5o/s400/pullups.jpg" alt="" id="BLOGGER_PHOTO_ID_5292364003190343458" border="0" /></a><br />Green and orange wires connect the two PICs together:<br /><br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4rVtbUstWrjbsO8oYn2Hl45QMX-Ux1Mji4FCCBlJ_u0eZBbNWQ9WYNvFPCsJleGkY3aIjZG2ZZj87HVEbKPUk05WsYuZVUyM9BDrq2rX_KTGYYKhGFvRnfrW7_uPI1JyjprmwLafHaUU/s1600-h/wires.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4rVtbUstWrjbsO8oYn2Hl45QMX-Ux1Mji4FCCBlJ_u0eZBbNWQ9WYNvFPCsJleGkY3aIjZG2ZZj87HVEbKPUk05WsYuZVUyM9BDrq2rX_KTGYYKhGFvRnfrW7_uPI1JyjprmwLafHaUU/s400/wires.jpg" alt="" id="BLOGGER_PHOTO_ID_5292364013765014130" border="0" /></a><br /><br />The goal of this test is simple: check if the i2c bus is properly built and operational. How ? PIC 16F88 and its SSP peripheral is able to be configured so it triggers an interrupts when a Start or Stop signal is detected. Read <a href="http://www.esacademy.com/faq/i2c/busevents/i2cstast.htm">this page</a> (part of an nice article on i2c, from last post's recommandations).<br /><br />How are we gonna test this ? The idea of this test is simple:<br /><br /><ol><li>On power, master will blink a LED a little, just to inform you it's alive</li><li>On the same time, slave is doing the same</li><li>Once master has done blinking, it sends a i2c frame through the bus</li><li>If the bus is properly built and configured, slave will infinitely blink its LED, at high speed<br /></li></ol><br />Note master will send its i2c frame to a specific address, which don't necessarily need to be the same as the slave one (and I recommand to use different addresses, just to make sure you understand what's going on).<br /><br />What about the sources ? <a href="http://code.google.com/p/jallib/downloads/list">Download</a> last jallib pack, then go get some other libraries and samples (those files aren't release yet, API may change):<br /><br /><ul><li><a href="http://jallib.googlecode.com/svn/trunk/include/peripheral/i2c/i2c_hw_slave.jal">i2c_hw_slave.jal</a> : copy this file in your "lib" directory</li><li><a href="http://jallib.googlecode.com/svn/trunk/sample/by_device/16f88/16f88_i2c_sw_master_check_bus.jal">16f88_i2c_sw_master_check_bus.jal</a> : code for master, put this in "sample" directory</li><li><a href="http://jallib.googlecode.com/svn/trunk/sample/by_device/16f88/16f88_i2c_hw_slave_check_bus.jal">16f88_i2c_hw_slave_check_bus.jal</a> : code for slave, put this file in "sample" directory</li></ul><br />(Edit on 01/30: those libraries and samples are now included in jallib's version > 0.1. No extra download needed)<br /><br /><br />The main part of the slave code is the way the initialization is done. A constant is declared, telling the library to enable Start/Stop interrupts [edit on 01/30, API has changed, previously init was taking a true/false parameter]:<br /><br /><pre><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">const SLAVE_ADDRESS = 0x23 -- whatever, it's not important, and can be</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;"> -- different from the address the master wants</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;"> -- to talk to</span><br /><span><span style="color: rgb(51, 0, 153); font-weight: bold;">-- with Start/Stop interrupts</span></span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">const bit i2c_enable_start_stop_interrupts = true<br /></span><span><span style="color: rgb(51, 0, 153); font-weight: bold;">-- this init automatically sets global/peripherals interrupts</span></span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">i2c_hw_slave_init(SLAVE_ADDRESS)</span><br /></pre><br /><br />And, of course, the Interrupt Service Routine (ISR):<br /><br /><pre><span style="font-family:mon;"><span style="color: rgb(51, 0, 153); font-weight: bold;">procedure i2c_isr() is</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;"> pragma interrupt</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;"> if ! PIR1_SSPIF then</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;"> return</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;"> end if</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;"> -- reset flag</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;"> PIR1_SSPIF = false</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;"> -- tmp store SSPSTAT</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;"> var byte tmpstat</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;"> tmpstat = SSPSTAT</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;"> -- check start signals</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;"> if (tmpstat == 0b_1000) then</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;"> -- If we get there, this means this is an SSP/I2C interrupts</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;"> -- and this means i2c bus is properly operational !!!</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;"> while true loop</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;"> led = on</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;"> _usec_delay(100000)</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;"> led = off</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;"> _usec_delay(100000)</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;"> end loop</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;"> end if</span><br /><span style="color: rgb(51, 0, 153); font-weight: bold;">end procedure</span><span style="font-weight: bold;"><br /></span></span><br /></pre><br /><br />The important thing is to:<br /><ul><li>check if interrupt is currently a SSP interrupts (I2C)</li><li>reset the interrupt flag,</li><li>analyze SSPSTAT to see if Start bit is detected</li><li>if so, blinks 'til the end of time (or your battery)<br /></li></ul><br /><br />Now, go compile both samples, and program two PICs with them. With a correct i2c bus setting, you should see the following:<br /><div style="text-align: center;"><br /></div><object height="344" width="425"><param name="movie" value="http://www.youtube.com/v/NalAkRhFP-s&hl=en&fs=1"><param name="allowFullScreen" value="true"><param name="allowscriptaccess" value="always"><embed src="http://www.youtube.com/v/NalAkRhFP-s&hl=en&fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" height="344" width="425"></embed></object><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div>On this next video, I've removed the pull-ups resistors, and it doesn't work anymore (slave doesn't high speed blink its LED).<br /><br /><div style="text-align: center;"><br /><object height="344" width="425"><param name="movie" value="http://www.youtube.com/v/cNK_cCgWctY&hl=en&fs=1"><param name="allowFullScreen" value="true"><param name="allowscriptaccess" value="always"><embed src="http://www.youtube.com/v/cNK_cCgWctY&hl=en&fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" height="344" width="425"></embed></object><br /></div><br /><br />Next time (and last time on this topic), we'll see how to implement the state machine using jallib, defining callback for each states.<br /><br />Reading:<br /><br /><ul><li><a href="http://jallib.blogspot.com/2009/01/step-by-step-building-i2c-slave-with.html">Part 1: a few words before getting our hands dirty...</a></li><li>Part 2: checking the hardware and the i2c bus...</li><li><a href="http://jallib.blogspot.com/2009/01/step-by-step-building-i2c-slave-with_20.html">Part 3: implementing an i2c slave ISR</a></li></ul><br /><br /><span style="font-style: italic;">Sébastien Lelong</span>Sebastien Lelonghttp://www.blogger.com/profile/00317258446230687333noreply@blogger.com0tag:blogger.com,1999:blog-8299212346186005351.post-29634673683810768072009-01-14T10:22:00.018+01:002009-01-25T10:56:00.404+01:00Step by Step: building an i2c slave with jallib (part 1)<span style="font-size:130%;"><span style="font-style: italic; font-weight: bold;">Part 1 : a few words before getting our hands dirty...</span></span><br /><br /><a href="http://en.wikipedia.org/wiki/I2c">i2c</a> is a nice protocol: it is quite fast, reliable, and most importantly, it's addressable. This means that on a single 2-wire bus, you'll be able to plug up to 128 devices using 7bits addresses, and even 1024 using 10bits address. Far enough for most usage... I won't cover i2c in depth, as there are <a href="http://www.google.com/search?q=i2c">plenty resources</a> on the Web (and I personally like <a href="http://www.esacademy.com/faq/i2c/index.htm">this page</a>).<br /><br />i2c is found in many chips and many modules. Most of the time, you create a master, like when <a href="http://code.google.com/p/jallib/source/browse/trunk/sample/by_device/16f88/16f88_i2c_sw_l1.jal">accessing an EEPROM</a>. This time, in this tutorial, we're going to build a slave, which will thus respond to master's requests.<br /><br />The <span style="font-style: italic;">slave side</span> is somewhat more difficult because, as it does not initiate the talk, it has to listen to "events", and be as responsive as possible. You've guessed, we'll use <span style="font-style: italic;">interrupts</span>. I'll only cover i2c hardware slave, that is using <span style="font-style: italic;">SSP peripheral</span> (note: some PICs have MSSP, this means they can also be used as i2c hardware Master). Implementing an i2c software slave may be very difficult (and I even wonder if it's reasonable...).<br /><br />There are different way implementing an i2c slave, but one seems to be quite common: defining a <a href="http://en.wikipedia.org/wiki/Finite_state_machine">finite state machine</a>. This implementation is well described in Microchip AppNote <a href="http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1824&appnote=en011798">AN734</a> . It is highly recommended that you read this appnote, and the i2c sections of your favorite PIC datasheet as well (I swear it's quite easy to read, and well explained).<br /><br />Basically, during an i2c communication, there can be <span style="font-weight: bold;">5 distinct states</span>:<br /><ol><li><span style="font-weight: bold;">Master writes, and last byte was an address</span> : to sum up, master wants to talk to a specific slave, identified by the address, it wants to send data (write)<br /></li><li><span style="font-weight: bold;">Master writes, and last byte was data</span> : this time, master sends data to the slave</li><li><span style="font-weight: bold;">Master read, and last byte was an address</span> : almost the same as 1., but this time, master wants to read something from the salve</li><li><span style="font-weight: bold;">Master read, and last byte was data</span> : just the continuation of state 3., master has started to read data, and still wants to read more data</li><li><span style="font-weight: bold;">Master sends a NACK</span> : basically, master doesn't want to talk to the slave anymore, it hangs up...<br /></li></ol><br />Note: in i2c protocol, one slave has actually two distinct addresses. One is for read operations, and it ends with bit 1. Another is for write operations, and it ends with bit 0.<br /><br />Ex: consider the following address (8-bits long, last bit is for operation type)<br /><br /><span style="color: rgb(51, 0, 153);"> 0x5C => 0b_0101_110</span><span style="font-weight: bold; color: rgb(51, 0, 153);">0</span><span style="color: rgb(51, 0, 153);"> => write operation</span><br /><br />The same address for read operation will be:<br /><br /><span style="color: rgb(51, 0, 153);"> 0x93 => 0b_0101_110</span><span style="font-weight: bold; color: rgb(51, 0, 153);">1</span><span style="color: rgb(51, 0, 153);"> = read operation</span><br /><br /><br />[EDIT:<span style="font-weight: bold;"> jallib currently supports up to 128 devices on a i2c bus</span>, using 7-bits long addresses (without the 8th R/W bits). There's currently no support for 10-bits addresses, which would give 1024 devices on the same bus. If you need it, please <a href="http://groups.google.com/group/jallib">let us know</a>, we'll modify libraries as needed !]<br /><br />OK, enough for today. Next time, we'll see how two PICs must be connected for i2c communication, and we'll check the i2c bus is fully working, before diving into the implementation.<br /><br /><br />Reading:<br /><br /><ul><li>Part 1: a few words before getting our hands dirty...</li><li><a href="http://jallib.blogspot.com/2009/01/step-by-step-building-i2c-slave-with_17.html">Part 2: checking the hardware and the i2c bus...</a></li><li><a href="http://jallib.blogspot.com/2009/01/step-by-step-building-i2c-slave-with_20.html">Part 3: implementing an i2c slave ISR</a></li></ul><br /><span style="font-style: italic;"><br />Sébastien Lelong</span>Sebastien Lelonghttp://www.blogger.com/profile/00317258446230687333noreply@blogger.com3tag:blogger.com,1999:blog-8299212346186005351.post-24087160789874457172009-01-13T07:34:00.009+01:002009-01-13T09:49:16.545+01:00Common pitfall: digital pins aren't digital unless explicitely set as digital<span style="color: rgb(0, 0, 0);">If you've read some jallib samples, you may have often seen this line:</span><br /><br /><span style="color: rgb(51, 0, 153);"><span>enable_digital_io() -- disable analog I/O (if any)</span></span><br /><br /><span style="color: rgb(0, 0, 0);">What does this mean and why ? This simply means you want to set all pins as digital pins. Because, <span style="color: rgb(102, 0, 0); font-weight: bold;">by default, pins are configured as analog pins</span>.<br /><br />Where does this come from ? From the holy datasheet, of course ! Consider the 16f88 chip. PORTA provides the following functions:<br /><br /><br /></span><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXTPVVoG0bDEue7GQZtT0mOas9qmOVJzc5GRg3aMUmIILwEUmT4LqOqcClSKSbGMxH1xbHN4hWZRieNThyWnf0Ij6dgXsH1OZnVVtWgPb0hU5UI11ihzsJ-SKFFhdIjbwtEmHsmKmOp_c/s1600-h/func_porta.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 203px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXTPVVoG0bDEue7GQZtT0mOas9qmOVJzc5GRg3aMUmIILwEUmT4LqOqcClSKSbGMxH1xbHN4hWZRieNThyWnf0Ij6dgXsH1OZnVVtWgPb0hU5UI11ihzsJ-SKFFhdIjbwtEmHsmKmOp_c/s400/func_porta.png" alt="" id="BLOGGER_PHOTO_ID_5290667131270533602" border="0" /></a><br /><span style="color: rgb(51, 0, 153);"><span style="color: rgb(0, 0, 0);">Amongst them, some provide analog function, such Analog-to-Digital-Conversion (ADC). And it's explicitly said the PORTA pins are configured as analog inputs on Power-on Reset:<br /><br /></span></span><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPElDuUaWj-N5hXwj1hHy37f2dlz2WGEDYK-OGSeTI94QW0cGsgd3k3Bon_nijQ7U4AgA69TRZ34fG7S_mpiQbycz3_hJ_dZ_Ft2aJf_NYbqhl0hHy0ee2kunpC6ko5c7PO7eaxRCewF4/s1600-h/analog_porta.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 314px; height: 59px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPElDuUaWj-N5hXwj1hHy37f2dlz2WGEDYK-OGSeTI94QW0cGsgd3k3Bon_nijQ7U4AgA69TRZ34fG7S_mpiQbycz3_hJ_dZ_Ft2aJf_NYbqhl0hHy0ee2kunpC6ko5c7PO7eaxRCewF4/s400/analog_porta.png" alt="" id="BLOGGER_PHOTO_ID_5290669368172789794" border="0" /></a><span style="color: rgb(51, 0, 153);"><span style="color: rgb(0, 0, 0);"><br />Datasheet is less explicit for PORTB. Two pins provide analog functions, for the last two ADC channels (pins RB6 and RB7):<br /><br /></span></span><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcKqTNAFLDq59E1ayPlcjwoGMP70jg3q2HeoKcfmCzJi4Ci5sHe1l2MyOuLjyhupxdg9LU_mekGWAaoxpvsbT-fdRSDXUZiNUZKOoTFjFaYYaE8TnZUoRA4Ezl5GJ5zeJTH0smcJgxzwU/s1600-h/func_portb.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 342px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcKqTNAFLDq59E1ayPlcjwoGMP70jg3q2HeoKcfmCzJi4Ci5sHe1l2MyOuLjyhupxdg9LU_mekGWAaoxpvsbT-fdRSDXUZiNUZKOoTFjFaYYaE8TnZUoRA4Ezl5GJ5zeJTH0smcJgxzwU/s400/func_portb.png" alt="" id="BLOGGER_PHOTO_ID_5290695860645380146" border="0" /></a><span style="color: rgb(51, 0, 153);"><span style="color: rgb(0, 0, 0);"><br /></span></span><span style="color: rgb(51, 0, 153);"><span style="color: rgb(0, 0, 0);">Those pins are configured with ANSEL register, which is read as 1 on Power-on Reset, which means by default, pins are configured as analog:<br /><br /></span></span><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjhw1vn5a9-Q2vr114Ve9uxQLkHmwUf-LwB7NOZi50VcXNf7VdTMnZvcV1ZdQKbIvj7f0NP4dH3u-qfnnGhk0bS4Jwc6OkXJIYm0wlNMcIOAyJwtLEHRow94gJc5gncLBrwhVpBIXFrcE/s1600-h/register_ansel.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 216px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjhw1vn5a9-Q2vr114Ve9uxQLkHmwUf-LwB7NOZi50VcXNf7VdTMnZvcV1ZdQKbIvj7f0NP4dH3u-qfnnGhk0bS4Jwc6OkXJIYm0wlNMcIOAyJwtLEHRow94gJc5gncLBrwhVpBIXFrcE/s400/register_ansel.png" alt="" id="BLOGGER_PHOTO_ID_5290669367341890594" border="0" /></a><br /><span style="color: rgb(51, 0, 153);"><span style="color: rgb(0, 0, 0);">Phew... Now why don't we, at jallib, set all pins as digital ? After all, most of the time, you need digital pins, and even if not, you could just set them as analog pins as needed. Yes, you could. But we decided to follow the holy datasheet. And this means if you read and know the datasheet, when you type this:<br /><br /><span style="color: rgb(51, 0, 153);">include 16f88</span><br /><br />you expect to get analog pins, because the datasheet says so. To switch them to digital pins, just call </span></span><span style="color: rgb(51, 0, 153);"><span>enable_digital_io()<span style="color: rgb(0, 0, 0);">. This procedure is the same for every PIC: whatever the device file you're using, calling this procedure will configure and setup all registers so you have digital pins (and there are many differencies and inconsistencies between PICs, fortunately thanks to Rob's hard work, this is made easy for users).<br /><br /></span></span></span><span style="color: rgb(51, 0, 153);"><span style="color: rgb(0, 0, 0);">So, one important point using jallib is: <span style="font-weight: bold;">"be explicit"</span>. While this may need more typing from you, you'll get a better understanding of what's going on, and you'll finally get a cleaner and more maintainable code.<br /><br /><span style="font-style: italic;">Sébastien Lelong</span><br /></span></span>Sebastien Lelonghttp://www.blogger.com/profile/00317258446230687333noreply@blogger.com0tag:blogger.com,1999:blog-8299212346186005351.post-89937394190172719862009-01-04T10:32:00.012+01:002009-01-13T07:33:37.899+01:00Common pitfall: setting up registers while using bootloaders<span style="font-family:arial;">I've recently been in trouble understanding how the 16F88's internal clock is working. Starting from a supposed i2c speed problem, I dive into internal clock's internals, with Joep, my guide... Here's what I learned.</span><br /><br /><span style="font-family:arial;">First of all, I like using internal clock, because it requires less parts, provides still nice performances and consume less energy, which is good when working on embedded systems. Maybe the major drawback is you can't reach a decent 115 200 bds for your serial communication.</span><br /><br /><span style="font-family:arial;">Anyway, I used to setup my 16f88 to run at 8 MHz. Yeah, just say:</span><br /><br /><span style="color: rgb(51, 0, 153);font-family:courier new;" >pragma target CLOCK 8_000_000<br /></span><span style="font-family:courier new;"><span style="color: rgb(51, 0, 153);">pragma target OSC INTOSC_NOCLKOUT</span><br /><br /><span style="font-family:arial;">and that's it, you'll run at 8 MHz... Will you ? Well, all my 16f88 always run @ 8MHz using this configuration. But Joep, the Grand Master of the Hidden Clock, said: "no you don't, because the holy datasheet says, by default (on power), this configuration will setup a clock running @ 31.25 KHz". Errr... 31.25 KHz, how can this be possible ? I'm sure it runs @ 8MHz. And why 31.25 KHz ? "Because IRCF bits are read as 0 when powered, see OSCCON register", said Joep the Grand Master.</span><br /><br /><span style="font-family:arial;">So I looked at OSCCON register:</span><br /><br /></span><a style="font-family: arial;" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgchCWuB8xyymq1fJQiSySVhAPbhyunip-qHZQO3Wxed_-ib0nZW49TAHFSt79r0bKhI27BK2AplWqjlpIezWJdUkTfclmQfpUyoDBbGbK1CyCusLnxv7gyZFywZvo94jU6trTtdJM1HHA/s1600-h/ocscon.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 153px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgchCWuB8xyymq1fJQiSySVhAPbhyunip-qHZQO3Wxed_-ib0nZW49TAHFSt79r0bKhI27BK2AplWqjlpIezWJdUkTfclmQfpUyoDBbGbK1CyCusLnxv7gyZFywZvo94jU6trTtdJM1HHA/s400/ocscon.png" alt="" id="BLOGGER_PHOTO_ID_5287373985143134482" border="0" /></a><br /><span style="font-family:courier new;"><br /><span style="font-family:arial;">Yes, now I can see OSCON_IRCF bits selects the appropriate internal clock speed. </span><span style="color: rgb(51, 0, 153);font-family:arial;" >IRCF = 0b_000</span><span style="font-family:arial;"> by default, and not </span><span style="color: rgb(51, 0, 153);font-family:arial;" >0b_111</span><span style="font-family:arial;">, which is the correct setting for an 8MHz clock.</span><br /><br /><span style="font-family:arial;">Still, I'm sure it's running @ 8MHz. It's like my 16f88 decided to set IRCF to 0b_111, despite what datasheet can say... How can this be possible ?</span><br /><br /><span style="font-family:arial;">Bootloaders... Yes, bootloaders can be sometime quite surprising. Because when using them, what you specify in your code about registers might not be what's programmed ! I use </span><a style="font-family: arial;" href="http://www.etc.ugal.ro/cchiculita/software/picbootloader.htm">Tiny bootloader</a><span style="font-family:arial;">, a very nice and small one. And I use the internal clock version for 16f88, running @ 8MHz. And Tiny bootloader code correctly setup the internal clock. So the "default" value becomes what Tiny has set: </span></span><span style="font-family:courier new;"><span style="color: rgb(51, 0, 153);font-family:arial;" >IRCF = 0b_111</span><span style="font-family:arial;"> that is, it runs @ 8MHz. Of course, you can still select the speed you want, by playing with IRCF, but the apparent default value is not what the datasheet says... Confusing :)</span><br /><br /><span style="font-family:arial;">So, to be accurate, the appropriate way to specify an internal clock running @ 8MHz for a 16f88 is:</span><br /><br /></span><span style="color: rgb(51, 0, 153);font-family:courier new;" >pragma target CLOCK 8_000_000<br /></span><span style="font-family:courier new;"><span style="color: rgb(51, 0, 153);">pragma target OSC INTOSC_NOCLKOUT<br />OSCCON_IRCF = 0b_111<br /><br /></span></span><span style="font-family:courier new;"><br /><span style="font-family:arial;">Another pitfall I usually fall into is </span><span style="color: rgb(51, 0, 153);font-family:arial;" >CCP1MUX</span><span style="font-family:arial;">. With this register, you can specify which pin, RB0 or RB3, will produce PWM for instance. Every time I set it to RB3, it just doesn't work. Why ? Because Tiny bootloader has set it to RB0. And this time, it cannot be changed, because Tiny bootloader (as any bootloader for PIC ?) cannot re-program such as register !</span><br /><br /><span style="color: rgb(51, 0, 51); font-weight: bold;font-family:arial;" ><span style="color: rgb(102, 0, 0);">If using a bootloader, remember, the actual program being originally uploaded to your PIC is not your program, it's the bootloader itself.</span> </span><span style="color: rgb(0, 0, 0);font-family:arial;" >So remember its proper configuration might conflict with your own, or at least confuse you...</span><br /><br /><span style="font-family:arial;">Solution ? Don't use bootloader, or be careful !</span><br /><br /><br /><br /></span>Sebastien Lelonghttp://www.blogger.com/profile/00317258446230687333noreply@blogger.com1tag:blogger.com,1999:blog-8299212346186005351.post-40049708016189845402008-12-29T18:57:00.005+01:002008-12-29T20:15:47.174+01:00non-blocking delays.<span style="font-family:arial;"><strong>Waiting...</strong></span><br /><span style="font-family:arial;">There are probably no JAL users that have not used delay.jal - the jallib library that let your program wait for a specified amount of time. Very usefull in most situations, but has one limitation: it blocks your program so can't do anything else while you are waiting. </span><br /><span style="font-family:arial;"></span><br /><br /><span style="font-family:arial;"><strong>Non-blocking delay</strong></span><br /><span style="font-family:arial;">Some applications need to take care of multiple tasks at the same time. Imagine a small robot, which has just decided it wants to move forward for 3 seconds. But while doing so, it has to guard it's front whiskers in case it runs into an object. A call like:</span><br /><br /><span style="font-family:courier new;">delay_100ms(30)</span><br /><br /><span style="font-family:arial;">would not allow this. This case requires a non-blocking delay, like the one provided by timer0_isr_interval.jal that generates an interrupt at a regular interval and has an ISR (Interrupt Service Routine) that deals with the delay you require.</span><br /><br /><span style="font-family:arial;"><strong>Software setup</strong></span><br /><span style="font-family:arial;">The setup of this library is straight-forward. First you define the interval of the interrupt you want. With a higher value, more interrupts are generated. This gives a higher resolution of your delay, but also puts a high background load on your PIC. Be carefull if you go beyond 1000 (1kHz). The lowest possible rate depends on the clock frequency you use and is 77 with an 16f877 on 20 MHz.</span><br /><br /><span style="font-family:arial;"><span style="font-family:courier new;">const timer0_isr_rate = 1000 -- 1 kHz isr rate</span> </span><br /><br /><span style="font-family:arial;">Next, you need to specify the number of slots. A slot is used to store the end-time of a delay-period so you need one slot for each concurrent delay.</span><br /><br /><span style="font-family:courier new;">const DELAY_SLOTS = 2 -- support 2 delays at the same time</span><br /><br /><span style="font-family:arial;">Now, include the library and call it's init function:</span><br /><br /><span style="font-family:courier new;">include timer0_isr_interval</span><br /><span style="font-family:courier new;">timer0_isr_init() -- init timer0 isr</span><br /><br /><span style="font-family:arial;"><strong>Blink!</strong></span><br /><span style="font-family:arial;">Now we are ready to use the delay functions. To demonstrate it's use, we take two LEDs and let them blink at their own interval:</span><br /><span style="font-family:arial;"></span><br /><br /><span style="font-family:courier new;">forever loop </span><br /><span style="font-family:courier new;"> if (check_delay(0)) then </span><br /><span style="font-family:courier new;"> set_delay(0, 409) -- 409 ticks on delay-slot 0</span><br /><span style="font-family:courier new;"> led = !led </span><br /><span style="font-family:courier new;"> end if </span><br /><span style="font-family:courier new;"> if (check_delay(1)) then </span><br /><span style="font-family:courier new;"> set_delay(1, 619) -- 619 ticks on delay-slot 1</span><br /><span style="font-family:courier new;"> led2 = !led2</span><br /><span style="font-family:courier new;"> end if</span><br /><span style="font-family:courier new;">end loop</span><br /><br /><span style="font-family:arial;">It's that simpe! check_delay() takes a slot number as a param and returns true if the delay has expired and false if it has not. When it has expired, the next delay is set with set_delay(). Note that the delay-parameter of this procedure is in 'ticks' - the number of times an interrupt occurs. In this example, we set the interrupt interval at 1000, so one tick is 1 milisecond.</span><br /><br /><span style="font-family:arial;">And then the only task left is to invert the led.</span><br /><br /><span style="font-family:arial;">In the above example, there are two LEDs blinking at a different (prime number) interval and it takes over 250.000 ticks for the pattern to repeat itself.</span><br /><br /><span style="font-family:arial;">Before I get to the conclusion of this article, there is one usefull feature I'd like to show you. The ISR also has (word) counter that is incremented at the tick rate. This is usefull if you want to execute tasks at isr interval, like scanning a keyboard:</span><br /><span style="font-family:arial;"></span><br /><span style="font-family:courier new;">if (isr_counter != prev_isr_counter) then<br />prev_isr_counter = isr_counter<br />-- put here code that you want<br />-- to execute each tick.<br />end if<br /></span><br /><span style="font-family:arial;">And if you want an other rate than every tick, use a delay slot!</span><br /><span style="font-family:arial;"></span><br /><span style="font-family:arial;"><strong>Epilogue</strong></span><br /><span style="font-family:arial;">We've seen an easy way to keep track of multiple delays. It enables you to create applications with complex timing. It also enables you to guard responses and act if there is none within the time set. And you can stop checking a delay or set it again (based on the time it is set again) when you feel like it.</span><br /><span style="font-family:arial;">But make sure you go trough you main loop at a fast rate and don't use the classic delay() functions. A blinking led in the main loop helps to detect blocking code that prevents execution of the main loop at a proper rate.</span><br /><span style="font-family:arial;"></span><br /><span style="font-family:arial;">The timer0_interval.jal samples of jallib provides a working example for the code shown. </span><br /><span style="font-family:arial;"></span><br /><span style="font-family:arial;">Joep Suijs</span><br /><p></p>Joep Suijshttp://www.blogger.com/profile/06821529393453332522noreply@blogger.com5tag:blogger.com,1999:blog-8299212346186005351.post-72349942019809997462008-12-13T18:00:00.007+01:002009-01-28T16:24:35.615+01:00Serial communication<span style="font-family:arial;">The serial port of a PIC controller enables you to exchange information with other devices. Personally, I hook up every PIC to my PC via the serial port to debug my programs in real time. How? After the blink example, follow the steps:</span><br /><br /><span style="font-family:arial;"><strong>Hardware setup</strong></span><br /><span style="font-family:arial;">There is a lot of info on serial port hardware setup on the Internet. To get started it is good to know:</span><br /><ul><li><span style="font-family:arial;">PC's all used to have serial ports with 9-pin male sub-D connectors. Today, standard serial ports become less common, especially on laptop computers. In case your PC does not have a serial port, get an USB to serial convertor.</span></li><br /><li><span style="font-family:arial;">Pin 2 and 3 of this connector contain the send and receive signal of the serial port. Pin 5 is ground.</span></li><br /><li><span style="font-family:arial;">The voltage on such a serial port range from +/- 3V to +/- 12V, wich is not compatible with the 0/5V range of PIC controlers. Use a 'level shifter' (often based on a max232 or alike) to convert the signal.</span></li><br /><li><span style="font-family:arial;">The output of the level shifter is connected to the RX and TX pin of the PIC.</span></li></ul><p><span style="font-family:arial;">If you need more info on this, Google is your friend!</span></p><p><span style="font-family:arial;"><strong>Software setup</strong></span><br /></p><p><span style="font-family:arial;">Now you have the hardware ready, you need to configure the Jallib serial_hardware lib, that uses the build-in USART to send and receive characters. </span></p><p><span style="font-family:Arial;">First, we have to set the desired speed:</span></p><p align="left"><span style="font-family:courier new;">const serial_hw_baudrate = 115_200</span></p><p><span style="font-family:arial;">Next, include the library and call init:</span></p><p><span style="font-family:courier new;">include serial_hardware</span></p><p><span style="font-family:courier new;">serial_hw_init()</span><br /></p><p><span style="font-family:arial;"><strong>Communicate!</strong></span></p><p><span style="font-family:arial;">Now you are ready to use the serial interface. So you can send a char like:</span></p><p><span style="font-family:courier new;">serial_hw_write("!")</span></p><p><span style="font-family:arial;">or use the pseudo-var interface to do the same:</span></p><p><span style="font-family:arial;"><span style="font-family:courier new;">serial_hw_data = "!"</span> </span></p><p><span style="font-family:arial;">To read a char, you can use the function serial_hw_read(). If there is a character waiting, it puts the char into the parameter var and returns true. If there is no character waiting, it returns false. So:</span></p><p><span style="font-family:courier new;">if serial_hw_read(char) then -- non-blocking</span></p><p><span style="font-family:courier new;">serial_hw_write(char) -- that's the echo... </span></p><p><span style="font-family:courier new;">end if</span></p><span style="font-family:arial;">echo's back each character it receives. Be sure to call serial_hw_read often enough so no characters are lost.</span><br /><span style="font-family:arial;"></span><br /><span style="font-family:arial;">An alternative way to receive characters is the pseudo-var:</span><br /><span style="font-family:arial;"></span><br /><span style="font-family:courier new;">char = serial_hw_data -- blocking receive</span><br /><span style="font-family:courier new;">serial_hw_data = char</span><br /><span style="font-family:arial;"></span><br /><span style="font-family:arial;">The first line puts the received character in variable char and the next echoes it back.</span><br /><span style="font-family:arial;">We've seen above that sending by the pseudo var is the same as calling the function. When receiving, there is a major difference: where there is no character waiting, function serial_hw_read immediately returns and program execution continues. This is called non-blocking. </span><br /><span style="font-family:arial;">When there is no character waiting when the pseudo-var is used, the program will wait until a valid character is received. So if it does not receive anything, it will wait forever!</span><br /><br /><span style="font-family:arial;"><strong>How to continue</strong></span><br /><span style="font-family:arial;">We've seen how to setup a hardware serial port, send characters and receive characters - either blocking or non-blocking. The test-program sample_serial_hardware.jal, provides a working example for the code shown. </span><br /><span style="font-family:arial;"></span><br /><span style="font-family:arial;">Joep Suijs</span>Joep Suijshttp://www.blogger.com/profile/06821529393453332522noreply@blogger.com0tag:blogger.com,1999:blog-8299212346186005351.post-51635861525943352722008-12-12T19:07:00.000+01:002008-12-13T16:32:02.279+01:00i2c master<span style="font-family:arial;">Do you want to read an i2c compass? Store data into an i2c eeprom? Jallib let your PIC act as an i2c master and provides a powerfull and clean interface. And it's easy to use. </span><br /><span style="font-family:arial;">After the blink example, follow the steps:</span><br /><span style="font-family:Arial;"></span><br /><span style="font-family:Arial;"><strong>Hardware setup.</strong></span><br /><span style="font-family:Arial;">First you have to setup the i2c bus hardware.</span><br /><span style="font-family:Arial;">The first thing to concider is if you can and want to use the MSSP to handle i2c (i2c hardware) or handle i2c in software.</span><br /><span style="font-family:Arial;">The first option - i2c hardware - is possible for most (but not all) PICs with MSSP. The advantage is that this option is generally faster then software i2c. If you choose i2c hardware, you will use the pre-defined i2c clock and i2c data pins. (scl and sda).</span><br /><span style="font-family:Arial;">With i2c in software, pick any free io pin for i2c clock and i2c data.</span><br /><span style="font-family:Arial;"></span><br /><span style="font-family:Arial;">Now you have choosen the pins, you need to setup the hardware. Connect clock, data and ground from the PIC to the i2c slave, place pull-up resistors (e.g. 1k5) from both clock and data to the pic power supply and power the slave device. For more details on this, check the i2c slave datasheet or look on the Internet.</span><br /><span style="font-family:Arial;"></span><br /><span style="font-family:Arial;"><strong>Software setup</strong></span><br /><span style="font-family:Arial;">Now you have the hardware ready, you need to configure the software.</span><br /><span style="font-family:Arial;"></span><br /><span style="font-family:Arial;">First, define the pins used, for example on an 16F877a:</span><br /><span style="font-family:courier new;">var volatile bit i2c_scl is pin_c3</span><br /><span style="font-family:courier new;">var volatile bit i2c_scl_direction is pin_c3_direction</span><br /><span style="font-family:courier new;">var volatile bit i2c_sda is pin_c4</span><br /><span style="font-family:courier new;">var volatile bit i2c_sda_direction is pin_c4_direction</span><br /><span style="font-family:Arial;"></span><br /><span style="font-family:Arial;">Second, define the next two constants:</span><br /><span style="font-family:courier new;">const word _i2c_bus_speed = 1 ; * 100kHz</span><br /><span style="font-family:courier new;">const bit _i2c_level = true ; i2c levels (not SMB)</span><br /><span style="font-family:courier new;"></span><br /><span style="font-family:arial;">And now you can include the 'level0' i2c library. This is the library that creates the i2c signals and comes in two flavors:</span><br /><span style="font-family:Arial;"></span><br /><span style="font-family:courier new;">include i2c_software</span><br /><span style="font-family:courier new;">i2c_initialize()</span><br /><span style="font-family:courier new;"></span><br /><span style="font-family:Arial;">or</span><br /><span style="font-family:Arial;"></span><br /><span style="font-family:courier new;">include i2c_hardware</span><br /><span style="font-family:courier new;">i2c_initialize() </span><br /><span style="font-family:Arial;"></span><br /><span style="font-family:Arial;">Both libraries have the same interface to send and receive bytes. You can build complex messages with this interface but in most cases, it is easier to use the level1 layer. To use this, define an array for transmit and an array for receive and include the library:</span><br /><span style="font-family:Arial;"></span><br /><span style="font-family:courier new;">var byte i2c_tx_buffer[6]</span><br /><span style="font-family:courier new;">var byte i2c_rx_buffer[10]<br />include i2c_level1</span><br /><span style="font-family:Arial;"></span><br /><span style="font-family:Arial;">The size of the two buffers are the maximum size of a message you will send or receive. When a buffer is too short, you might get compile errors or - worse - unexpected behavior. When the buffers are too long, memory will be exhausted faster. When in doubt: enlarge the buffer a few bytes!</span><br /><span style="font-family:Arial;"></span><br /><span style="font-family:Arial;"><strong>Read from an i2c eeprom</strong></span><br /><span style="font-family:Arial;">Now we are ready to communicate with the i2c slave. The format of the messages depend on the device, so you should consult the slave's documentation. There is an example below of communicating with an i2c eeprom (24lc256). </span><br /><span style="font-family:Arial;">First thing to know of a slave is it's address. An i2c address is 7 bits and is stored in the higher 7 bits of a byte. The lowest bit is set to zero. The i2c eeprom address is </span><span style="font-family:Arial;">0xA0 (160 decimal).</span><br /><span style="font-family:Arial;">Now we want to read data from the eeprom. Let's assume we want to start at internal (eeprom) location 1234 and need 3 bytes. From the 24lc256 datasheet, we learn that we have to write a 2-byte (= one word) location. Subsequently, we can read data. Or in JAL:</span><br /><span style="font-family:Arial;"></span><br /><span style="font-family:courier new;">-- Send word location to device 0xA0 and read 3 bytes data </span><br /><span style="font-family:courier new;">r = i2c_receive_wordaddr(0xA0, 1234, 3)</span><br /><br /><span style="font-family:courier new;">print_byte_hex(serial_hw_data, i2c_rx_buffer[0]); </span><br /><span style="font-family:courier new;">serial_hw_data = " " </span><br /><span style="font-family:courier new;">print_byte_hex(serial_hw_data, i2c_rx_buffer[1]); </span><br /><span style="font-family:courier new;">serial_hw_data = " " </span><br /><span style="font-family:courier new;">print_byte_hex(serial_hw_data, i2c_rx_buffer[2]); </span><br /><span style="font-family:courier new;">print_crlf(serial_hw_data)</span><br /><span style="font-family:Arial;"></span><br /><span style="font-family:Arial;">So only one call to i2c_receive_wordaddr to do the i2c write and read! This function takes 3 params: the i2c slave device address, the value of the 2-byte location code and the number of byte to read after the location code is sent.</span><br /><span style="font-family:Arial;">The result is stored in i2c_rx_buffer[] and is printed on the serial port by the example. (Have a look at 'print_serial_numbers.jal' for more details on the use of serial comms.)</span><br /><span style="font-family:Arial;">You might have notices the return value r in the sample above. This bit value is true if the operation was succesfull. If false, communication has failed. Add code to check the return value and handle errors in your program!</span><br /><span style="font-family:Arial;"></span><br /><span style="font-family:Arial;">i2c_receive_byteaddr is a similar function which uses a 1-byte location code. </span><br /><span style="font-family:Arial;"></span><br /><span style="font-family:Arial;">Arbitrary location code lengths can be sent by using i2c_send_receive. This function is used in the example below.</span><br /><span style="font-family:Arial;"></span><br /><span style="font-family:Arial;"><strong>Write to an i2c eeprom</strong></span><br /><span style="font-family:Arial;">In most cases, you also want to write to the eeprom. This is how you write value 99 to location 2 of the eeprom:</span><br /><span style="font-family:Arial;"></span><span style="font-family:Arial;"></span><br /><span style="font-family:courier new;">-- write part (increment 3rd byte at 0x0002)</span><br /><span style="font-family:courier new;">i2c_tx_buffer[0] = 0 -- high byte location in i2c eeprom</span><br /><span style="font-family:courier new;">i2c_tx_buffer[1] = 2 -- low byte location in i2c eeprom</span><br /><span style="font-family:courier new;">i2c_tx_buffer[2] = 99 -- data</span><br /><span style="font-family:courier new;">r = i2c_send_receive(0xA0, 3, 0) </span><br /><span style="font-family:courier new;"></span><span style="font-family:Arial;"></span><br /><span style="font-family:Arial;">Function i2c_send_receive takes the slave address as the first parameter. The second one defines the number of bytes to be sent to the slave from i2c_tx_buffer. The third param defines the number of bytes to be received from the slave (and stored in i2c_rx_buffer). In the example above, we don't want to receive any information so the third param is 0 and i2c_rx_buffer is not used.</span><br /><span style="font-family:Arial;"></span><br /><span style="font-family:Arial;"><strong>How to continue.</strong></span><br /><span style="font-family:Arial;">We've seen how to setup an i2c master, either using hardware or software. And we read data from an i2c eeprom and wrote a byte to it. The test-program test_i2c_sw_l1.jal, preceded by a board file like board_16f877a_dwarf.jal, provides a working example for the code shown. And in the near future, we intend to add samples of i2c code to jallib that are ready to compile. Adapt it to your specific slave and off you go!</span><br /><span style="font-family:Arial;">And if you can't get it to work, spent 2 euro on an 24lc256 as a 'i2c reference device', so you can check if your PIC and it's program are working like they should.</span><br /><span style="font-family:Arial;"></span><br /><span style="font-family:Arial;"></span><br /><span style="font-family:Arial;">Joep Suijs</span><br /><span style="font-family:Arial;"></span><br /><span style="font-family:Arial;"></span><br /><br /><span style="font-family:arial;"></span>Joep Suijshttp://www.blogger.com/profile/06821529393453332522noreply@blogger.com1tag:blogger.com,1999:blog-8299212346186005351.post-77856760385335026612008-12-12T14:42:00.000+01:002008-12-12T14:44:29.378+01:00jalliblogHi all,<br /><br />This is a blog dedicated to <a href="http://jallib.googlecode.com">jallib</a>, a set of libraries of jalv2 compiler. You'll find here interesting projects, thoughts, suggestions, etc... Feel free to add comments and feedback.<br /><br />Have fun !<br />SebSebastien Lelonghttp://www.blogger.com/profile/00317258446230687333noreply@blogger.com2