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

<channel>
	<title>Kerry D. Wong</title>
	<atom:link href="http://www.kerrywong.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.kerrywong.com</link>
	<description></description>
	<lastBuildDate>Fri, 03 Sep 2010 00:51:09 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>A Digital Level Using Accelerometer</title>
		<link>http://www.kerrywong.com/2010/09/02/a-digital-level-using-accelerometer/</link>
		<comments>http://www.kerrywong.com/2010/09/02/a-digital-level-using-accelerometer/#comments</comments>
		<pubDate>Fri, 03 Sep 2010 00:51:09 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[AVR/Arduino]]></category>
		<category><![CDATA[Accelerometer]]></category>
		<category><![CDATA[Arduino]]></category>
		<category><![CDATA[Atmega328P]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=2504</guid>
		<description><![CDATA[To measure how flat a surface is, you typically will need a level of some sort. In this article, I will show you a digital level I made with an accelerometer. It is extremely accurate, capable of measuring inclination as small as 1/1000 degree. The digital accelerometer I used here is ST&#8217;s triple-axis accelerometer LIS3LV02DL. [...]]]></description>
			<content:encoded><![CDATA[<p>To measure how flat a surface is, you typically will need a <a href="http://en.wikipedia.org/wiki/Spirit_level">level</a> of some sort. In this article, I will show you a digital level I made with an <a href="http://en.wikipedia.org/wiki/Accelerometer">accelerometer</a>. It is extremely accurate, capable of measuring inclination as small as 1/1000 degree. <span id="more-2504"></span></p>
<p>The digital accelerometer I used here is ST&#8217;s triple-axis accelerometer <a href="http://www.st.com/stonline/products/literature/ds/12094/lis3lv02dl.pdf">LIS3LV02DL</a>. I talked about how to use it using SPI <a href="http://www.kerrywong.com/2010/04/17/interfacing-lis3lv02dl-using-spi-ii/">a couple of months ago</a>. You only need 2 axises for this particular application, since I happen to have this tripe-axis accelerometer on hand, I will use it here.</p>
<p>The following are the coordinates of the acceleration measurements.<br />
<div id="attachment_2514" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/09/lis3lv02dlaxis.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/09/lis3lv02dlaxis-300x230.jpg" alt="LIS3LV02DL Orientation" title="LIS3LV02DL Orientation" width="300" height="230" class="size-medium wp-image-2514" /></a><p class="wp-caption-text">LIS3LV02DL Orientation</p></div></p>
<p>If we are measuring the surface represented by x-axis and y-axis, the angles can be measured as:<br />
\[\theta_x = tan^{-1}\frac{g}{g_x}\]<br />
\[\theta_y = tan^{-1}\frac{g}{g_y}\]</p>
<p>When the accelerometer is placed on a perfectly flat surface, the force exerted on z axis would be approximately 1g.</p>
<p>Since LIS3LV02DL has 2 modes (2g and 6g), the 12 bit of resolution per axis (readings from -2048 to 2048) should give us 1/1000 resolution in 2g mode. 6g model can also be used, but the accuracy will be roughly three times lower than in 2g mode. Here is the schematics of the circuit using ATmega328p MCU:</p>
<div id="attachment_2530" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/09/digitallevel.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/09/digitallevel-300x195.png" alt="LIS3LV02DL Digital Level " title="LIS3LV02DL Digital Level " width="300" height="195" class="size-medium wp-image-2530" /></a><p class="wp-caption-text">LIS3LV02DL Digital Level </p></div>
<p>In my design above, I used one button to toggle the back light of the LCD display, one button to calibrate the device and one button to toggle between 2g and 6g modes. Here is a picture of the assembled digital level. </p>
<div id="attachment_2533" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/09/digitallevel1.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/09/digitallevel1-300x225.jpg" alt="Digital Level" title="Digital Level" width="300" height="225" class="size-medium wp-image-2533" /></a><p class="wp-caption-text">Digital Level</p></div>
<p>The picture below shows the digital level on a flat surface after initial calibration. Calibration is achieved by placing the digital level on a known flat surface and press the calibrate button. When the calibration button is pressed, the x and y readings are forced to 0&#8242;s and thus making relative measurements much easier.</p>
<div id="attachment_2534" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/09/digitallevel2.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/09/digitallevel2-300x225.jpg" alt="Digital Level" title="Digital Level" width="300" height="225" class="size-medium wp-image-2534" /></a><p class="wp-caption-text">Digital Level</p></div>
<p>The Arduino code for this project can be downloaded <a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/09/DigitalLevel.tar.gz">here</a>. This project was developed with the NetBeans IDE and you may need to adjust the included header files if you are using Arduino IDE. For more information, please see <a href="http://www.kerrywong.com/2010/05/16/arduino-development-using-netbeans/">my previous article on this topic</a>.)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2010/09/02/a-digital-level-using-accelerometer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>POV And POV Image Encoder</title>
		<link>http://www.kerrywong.com/2010/08/19/pov-and-pov-image-encoder/</link>
		<comments>http://www.kerrywong.com/2010/08/19/pov-and-pov-image-encoder/#comments</comments>
		<pubDate>Thu, 19 Aug 2010 23:37:35 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[AVR/Arduino]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[Arduino]]></category>
		<category><![CDATA[Atmega328P]]></category>
		<category><![CDATA[C Sharp (C#)]]></category>
		<category><![CDATA[POV]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=2430</guid>
		<description><![CDATA[One of my recent projects was to build a POV display device. There are already many microcontroller based POV devices out there, but most of those I have seen use around eight LEDs and have fixed font types. So I thought of developing something that is larger (e.g. using more LEDs) and more flexible (e.g. [...]]]></description>
			<content:encoded><![CDATA[<p>One of my recent projects was to build a POV display device. There are already many microcontroller based <a href="http://en.wikipedia.org/wiki/Persistence_of_vision">POV</a> devices out there, but most of those I have seen use around eight <a href="http://en.wikipedia.org/wiki/Light-emitting_diode">LEDs</a> and have fixed font types. So I thought of developing something that is larger (e.g. using more LEDs) and more flexible (e.g. can display both text and images).<span id="more-2430"></span></p>
<p>Without using any <a href="http://en.wikipedia.org/wiki/Shift_register">shift registers</a>, a single ATmega328p chip can handle a around 20 I/O ports. I decided to use 16 LEDs, twice the number of LEDs as the ones you commonly see. This gives me at least four free pins for other purposes. You can probably build a POV with around 20 LEDs, but If you need more than that, you will have to use shift registers to expand the available IO pins or change to a chip that has more built-in IO pins (i.e. ATMega1280). But as you shall see later, the image generation process will be considerably more complex and the required memory storage will be much larger as well.</p>
<h3>POV Display and Its Synchronization</h3>
<p>In order to achieve a stable image output, the image frames generated by the POV device must be synchronized. A POV display can operate as a hand device (e.g. a wand) or be driven by a motor. When the POV device is built for hand use, it usually has a motion detector (from simple spring-in-cylinder switch to the more exotic accelerometer) so that the device can start displaying when the hand is waved. I decided to go with a motor driven design so that I can have more precise control over the output image. In this approach, image frames must be synchronized for each full rotation. A simple way to detect the motor rotation is to use a IR transmitter and receiver.</p>
<p>The following is the full design of my POV display (the left side shows the optical triggering mechanism mentioned above):</p>
<div id="attachment_2443" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/08/POV_schematics.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/08/POV_schematics-300x188.png" alt="16 LED POV Schematics" title="16 LED POV Schematics" width="300" height="188" class="size-medium wp-image-2443" /></a><p class="wp-caption-text">16 LED POV Schematics</p></div>
<p>And here is the finished circuit mounted on a motorized rotating platform:</p>
<div id="attachment_2453" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/08/POV_1.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/08/POV_1-300x225.jpg" alt="16 LED POV Display (top view)" title="16 LED POV Display (top view)" width="300" height="225" class="size-medium wp-image-2453" /></a><p class="wp-caption-text">16 LED POV Display (top view)</p></div>
<p>Here is a picture of the side view, you can see how the IR transmitter and receiver circuits are mounted. Whenever the transmitter and the receiver line up (it happens every rotation), the transistor would output a LOW signal to the ATMega328p (pin 28, Arduino analog pin 5) which indicates the beginning of a new frame. To reduce the light interference from the environment, the receiver is mounted on the rotor so it is facing downwards.</p>
<div id="attachment_2454" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/08/POV_2.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/08/POV_2-300x225.jpg" alt="16 LED POV Display (side view)" title="16 LED POV Display (side view)" width="300" height="225" class="size-medium wp-image-2454" /></a><p class="wp-caption-text">16 LED POV Display (side view)</p></div>
<h3>Image Encoder</h3>
<p>Building the circuit is only half of the game. In order to provide the most flexible and the richest displays, I decided to build a image encoder which can be used to automatically translates a binary image into the appropriate code that is needed for the POV display. For simple POV displays, the display patterns can be mapped directly into a binary two dimensional array, with 1 represents LED on and 0 represents LED off. But this approach is not practical when displaying larger images. For an image the size of 16&#215;100, 1600 bytes would be required to store the image information. This might not sound like much but that is almost all of ATMega328&#8242;s usable SRAM. Of course, you can always store the data structure off in Flash memory using <a href="http://www.arduino.cc/en/Reference/PROGMEM">PROGMEM</a>, but it is not the most efficient way to do so. A better approach would be to pack these pixels into bytes so that each byte can represent 8 pixel values.</p>
<p>This code is shown as below. This C# code works with both Microsoft&#8217;s .Net platform or Mono.Net and thus it can be run on either Windows or Linux:</p>
<pre class="brush: csharp;">
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;

namespace convertImg
{
	class Program
	{
		static void Main (string[] args)
		{
			if (args.Length != 1) return;

			Image img = Image.FromFile (args[0]);			

			Bitmap bm = new Bitmap (img);
			BitmapData bmd = bm.LockBits (new Rectangle (0, 0, img.Width, img.Height),
			                              ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

			byte[,] ay = new byte[img.Width, img.Height];
			byte[] compactedAy = new byte[2 * img.Width];

			for (int y = 0; y &lt; img.Height; y++) {
				for (int x = 0; x &lt; img.Width; x++) {
					byte b = Marshal.ReadByte (bmd.Scan0, y * bmd.Stride + x * 4);

					if (b == 0)
						ay[x, y] = 1;
					else
						ay[x, y] = 0;

					Console.Write (ay[x, y]);
				}

				Console.WriteLine ();
			}

			Console.Write (&quot;byte dispArray[] = {&quot;);

			for (int x = 0; x &lt; img.Width; x++) {
				if (x % 8 == 0) {
					Console.WriteLine ();
					Console.Write (&quot;\t&quot;);
				}

				compactedAy[2 * x] = (byte)(ay[x, 0] &lt;&lt; 7 |
				                            ay[x, 1] &lt;&lt; 6 |
				                            ay[x, 2] &lt;&lt; 5 |
				                            ay[x, 3] &lt;&lt; 4 |
				                            ay[x, 4] &lt;&lt; 3 |
				                            ay[x, 5] &lt;&lt; 2 |
				                            ay[x, 6] &lt;&lt; 1 |
				                            ay[x, 7]);			

				compactedAy[2 * x + 1] = (byte)(ay[x, 8] &lt;&lt; 7 |
				                                ay[x, 9] &lt;&lt; 6 |
				                                ay[x, 10] &lt;&lt; 5 |
				                                ay[x, 11] &lt;&lt; 4 |
				                                ay[x, 12] &lt;&lt; 3 |
				                                ay[x, 13] &lt;&lt; 2 |
				                                ay[x, 14] &lt;&lt; 1 |
				                                ay[x, 15]);

				if (x &lt; img.Width - 1) {
					Console.Write (&quot;{0,3} &quot;, compactedAy[2 * x]);
					Console.Write (&quot;, &quot;);
					Console.Write (&quot;{0,3} &quot;, compactedAy[2 * x + 1]);
					Console.Write (&quot;, &quot;);
				} else {
					Console.Write (&quot;{0,3} &quot;, compactedAy[2 * x]);
					Console.Write (&quot;, &quot;);
					Console.Write (&quot;{0,3} &quot;, compactedAy[2 * x + 1]);
				}
			}

			Console.WriteLine ();
			Console.WriteLine (&quot;};&quot;);
		}
	}
}
</pre>
<p>The code above converts a binary image into an array of packed bytes. Every vertical line consists of 16 pixels (since we are using 16 LEDs) which is translated into two consecutive bytes in the resulting array. In general, the more LEDs you have, the more space it would take for each encoded line. As you can see, making the number of LEDs divisible by eight enables us to use full bytes for each encoded line. It is possible to use number of LEDs that do not fall into this pattern, but the resulting code would be either more difficult if full byte utilization is desired or leave some unused space between each line if lines need to start on byte boundaries. </p>
<p>Here is our test image.</p>
<div id="attachment_2462" class="wp-caption aligncenter" style="width: 110px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/08/ImageToBeDisplayed.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/08/ImageToBeDisplayed.png" alt="Image to be Displayed" title="Image to be Displayed" width="100" height="16" class="size-full wp-image-2462" /></a><p class="wp-caption-text"> </p></div>
<p>Using the image above (in PNG format) as the input, the encoded image is outputted to the terminal (formatted as a C++ array)</p>
<pre class="brush: cpp;">
byte dispArray[] = {
    0, 2, 0, 30, 0, 252, 7, 240, 31, 48, 252, 48, 224, 48, 252, 48,
    31, 48, 7, 240, 0, 252, 0, 30, 0, 2, 0, 0, 0, 0, 0, 0,
    15, 254, 15, 254, 6, 0, 12, 0, 12, 0, 12, 0, 0, 0, 1, 240,
    7, 252, 14, 14, 12, 6, 12, 6, 12, 6, 12, 6, 6, 12, 255, 254,
    255, 254, 0, 0, 0, 0, 0, 0, 0, 0, 15, 248, 15, 252, 0, 14,
    0, 6, 0, 6, 0, 6, 0, 12, 15, 254, 15, 254, 0, 0, 0, 0,
    0, 0, 0, 0, 207, 254, 207, 254, 0, 0, 0, 0, 0, 0, 0, 0,
    15, 254, 15, 254, 6, 0, 12, 0, 12, 0, 12, 0, 14, 0, 7, 254,
    3, 254, 0, 0, 0, 0, 0, 0, 1, 240, 7, 252, 6, 12, 12, 6,
    12, 6, 12, 6, 12, 6, 6, 12, 7, 252, 1, 240, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 3, 192, 12, 48, 48, 12, 32, 4, 76, 2,
    76, 66, 128, 33, 128, 17, 128, 17, 128, 17, 76, 34, 76, 66, 32, 4,
    48, 12, 12, 48, 3, 192, 0, 0
};
</pre>
<p>and is ready to be consumed by the Arduino side of the code.</p>
<h3>Arduino Code</h3>
<p>And here is the code on the Arduino side (I used Netbeans as my IDE, and you may need to change a couple of the includes if you are using the IDE bundled with Arduino. For more information, please see <a href="http://www.kerrywong.com/2010/05/16/arduino-development-using-netbeans/">my previous article on this</a>.)</p>
<p>As you can see, the <i>dispArray</i> is plugged in directly from the output of the encoder shown above. Note that here I assumed the image size is 16&#215;100, if your image widths are different, then you will need to adjust the range of <i>curPos</i> accordingly.</p>
<p>The analogRead() statement in the main loop detects whether the IR transmitter and receiver are aligned. If so, the analog pin output would become lower as the transistor on the receiver side becomes saturated and when a pre-defined threshold is crossed, the decoding process begins. Depending on how fast the display spins, <i>colDelay</i> may need to be adjusted accordingly.</p>
<pre class="brush: cpp;">
#include &lt;binary.h&gt;
#include &lt;HardwareSerial.h&gt;
#include &lt;pins_arduino.h&gt;
#include &lt;WConstants.h&gt;
#include &lt;wiring.h&gt;
#include &lt;wiring_private.h&gt;
#include &lt;WProgram.h&gt;
#include &lt;EEPROM/EEPROM.h&gt;

const int p1 = 0; //2;
const int p2 = 1; //3;
const int p3 = 2; //4;
const int p4 = 3; //5;
const int p5 = 4; //6;
const int p6 = 5; //11;
const int p7 = 6; //12;
const int p8 = 7; //13;
const int p9 = 8; //14;
const int p10 = 9; //15;
const int p11 = 10; //16;
const int p12 = 14; //23;
const int p13 = 15; //24;
const int p14 = 16; //25;
const int p15 = 17; //26;
const int p16 = 18; //27;

const int triggerPin = 5; //28;

const int colDelay = 8;

int ledPins[] = {p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16};
int curPos = 0;

/** Image generator output */
byte dispArray[] = {
    0, 2, 0, 30, 0, 252, 7, 240, 31, 48, 252, 48, 224, 48, 252, 48,
    31, 48, 7, 240, 0, 252, 0, 30, 0, 2, 0, 0, 0, 0, 0, 0,
    15, 254, 15, 254, 6, 0, 12, 0, 12, 0, 12, 0, 0, 0, 1, 240,
    7, 252, 14, 14, 12, 6, 12, 6, 12, 6, 12, 6, 6, 12, 255, 254,
    255, 254, 0, 0, 0, 0, 0, 0, 0, 0, 15, 248, 15, 252, 0, 14,
    0, 6, 0, 6, 0, 6, 0, 12, 15, 254, 15, 254, 0, 0, 0, 0,
    0, 0, 0, 0, 207, 254, 207, 254, 0, 0, 0, 0, 0, 0, 0, 0,
    15, 254, 15, 254, 6, 0, 12, 0, 12, 0, 12, 0, 14, 0, 7, 254,
    3, 254, 0, 0, 0, 0, 0, 0, 1, 240, 7, 252, 6, 12, 12, 6,
    12, 6, 12, 6, 12, 6, 6, 12, 7, 252, 1, 240, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 3, 192, 12, 48, 48, 12, 32, 4, 76, 2,
    76, 66, 128, 33, 128, 17, 128, 17, 128, 17, 76, 34, 76, 66, 32, 4 of,
    48, 12, 12, 48, 3, 192, 0, 0
};

/**
 * delay ms * 0.1 milliseconds
 */
void delayMilliseconds(int ms) {
    for (int i = 0; i &lt; ms; i++) {
        delayMicroseconds(100);
    }
}

void setup() {
    for (int i = 0; i &lt; 16; i++) {
        pinMode(ledPins[i], OUTPUT);
        digitalWrite(ledPins[i], LOW);
    }
}

void loop() {
    if (analogRead(triggerPin) &lt; 800) {
        for (int curPos = 99; curPos &gt;= 0; curPos--) {
            byte b1 = dispArray[curPos * 2];
            byte b2 = dispArray[curPos * 2 + 1];

            for (int i = 0; i &lt; 8; i++) {
                digitalWrite(ledPins[i + 8], (b1 &amp; (1 &lt;&lt; i)) &gt;&gt; i);
                digitalWrite(ledPins[i], (b2 &amp; (1 &lt;&lt; i)) &gt;&gt; i);
            }

            delayMilliseconds(colDelay);
        }

        for (int i = 0; i &lt; 16; i++) {
            digitalWrite(ledPins[i], LOW);
        }
    }
}
</pre>
<h3>POV Display in Action</h3>
<p>Here&#8217;s the POV display in action. Using the programs in this article what you can show on this POV display is not just limited to characters, any binary image design that fits the image dimension (16&#215;100 in this example) can be used. If you use different images for different frames you can even create your own POV animation.</p>
<div id="attachment_2457" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/08/POV_3.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/08/POV_3-300x225.jpg" alt="16 LED POV Display in Action" title="16 LED POV Display in Action" width="300" height="225" class="size-medium wp-image-2457" /></a><p class="wp-caption-text">16 LED POV Display in Action</p></div>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2010/08/19/pov-and-pov-image-encoder/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Apache2 Logrotate</title>
		<link>http://www.kerrywong.com/2010/08/11/apache2-logrotate/</link>
		<comments>http://www.kerrywong.com/2010/08/11/apache2-logrotate/#comments</comments>
		<pubDate>Thu, 12 Aug 2010 00:14:04 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Linux/BSD]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Logrotate]]></category>
		<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=2422</guid>
		<description><![CDATA[Whenever I setup a new web server, I always like the idea of keeping the Apache logs roated on a daily basis. While the procedures for changing the log rotate frequency is pretty straight forward, I have seen a lot of people having problems with it so I decided to document it. To change the [...]]]></description>
			<content:encoded><![CDATA[<p>Whenever I setup a new web server, I always like the idea of keeping the <a href="http://www.apache.org">Apache</a> logs roated on a daily basis. While the procedures for changing the log rotate frequency is pretty straight forward, I have seen a lot of people having problems with it so I decided to document it.<span id="more-2422"></span></p>
<p>To change the Apache log rotate frequency, you would want to change the apache2 configuration file located under /etc/logrotate.d. Configurations located in this directory overrides the default settings in /etc/logrotate.conf (the configurations in /etc/logrotate.d are included in logrotate.conf)</p>
<p>Here&#8217;s what my settings look like (note that I had commented out compress option so that all the logs can be easily browsed):</p>
<blockquote><p>
/var/log/apache2/*.log {<br />
        daily<br />
        missingok<br />
        rotate 365<br />
        #compress<br />
        #delaycompress<br />
        notifempty<br />
        create 640 root adm<br />
        sharedscripts<br />
        postrotate<br />
                if [ -f "`. /etc/apache2/envvars ; echo ${APACHE_PID_FILE:-/var/run/apache2.pid}`" ]; then<br />
                        /etc/init.d/apache2 reload > /dev/null<br />
                fi<br />
        endscript<br />
}
</p></blockquote>
<h3>Common problem</h3>
<p>A common problem after changing the log rotate frequency is that the Apache logs do not appear to be rotating daily even though the configuration file had been changed correctly.</p>
<p>This seems to be a known issue with logrotate. If you read the manual for logrotate you&#8217;d see the following explanation:</p>
<blockquote><p>
       -f, &#8211;force<br />
              Tells logrotate to force the rotation, even if it doesn&#8217;t  think<br />
              this  is  necessary.   Sometimes this is useful after adding new<br />
              entries to a logrotate config file, or if  old  log  files  have<br />
              been removed by hand, as the new files will be created, and<br />
              logging will continue correctly.
</p></blockquote>
<p>Since the default cron daily job does not force the log rotation, you may want to add -f parameter to /etc/cron.daily/logrotate:</p>
<blockquote><p>
#!/bin/sh</p>
<p>test -x /usr/sbin/logrotate || exit 0<br />
/usr/sbin/logrotate -f /etc/logrotate.conf
</p></blockquote>
<p>With this change, the logs will be forced to rotate daily according to the setup.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2010/08/11/apache2-logrotate/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Weekend Server Upgrade &#8211; Update</title>
		<link>http://www.kerrywong.com/2010/08/02/weekend-server-upgrade-update/</link>
		<comments>http://www.kerrywong.com/2010/08/02/weekend-server-upgrade-update/#comments</comments>
		<pubDate>Tue, 03 Aug 2010 01:30:36 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Miscellaneous]]></category>
		<category><![CDATA[Ubuntu 10.04 Server]]></category>
		<category><![CDATA[Ubuntu Server]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=2415</guid>
		<description><![CDATA[Well, there is an old saying:&#8220;There&#8217;s no such thing as a free lunch.&#8221; After yesterday&#8217;s server upgrade, everything worked pretty well till sometime late this afternoon. At first I noticed that the database was down, but when I finally got to the console after work, it appeared that the server had crashed for some reason. [...]]]></description>
			<content:encoded><![CDATA[<p>Well, there is an old saying:<em>&#8220;There&#8217;s no such thing as a free lunch.&#8221;</em> After <a href="http://www.kerrywong.com/2010/08/01/weekend-server-upgrade/">yesterday&#8217;s server upgrade</a>, everything worked pretty well till sometime late this afternoon.<span id="more-2415"></span> </p>
<p>At first I noticed that the database was down, but when I finally got to the console after work, it appeared that the server had crashed for some reason. So naturally, I powered down the server and rebooted. But nothing happened, there was no POST message. At first I thought this was just a temporary glitch of some kind, but after repeated reboot attempts it became apparent that something was seriously wrong. I swapped RAM and CPU and tried a few other tricks but the machine refused to show any sign of life&#8230; I guess that somehow the old hand-me-down server had just bit the dust.</p>
<p>I could have just powered back on my old server but since I had intended to upgrade to Ubuntu 10.04 (my old server was running Ubuntu 8.04) I decided to run my server under VMWare for the time being till I get a chance to upgrade my old server to 10.04 first. </p>
<p>I guess I will have to live with my old Pentium III server for a bit longer. But hey, old as it is, it only consumes 40W of power!</p>
<p><em>Update 8/3/2010</em><br />
I have switched back to my old server. As I mentioned yesterday, I upgraded the server to Ubuntu 10.04. So everything is back to normal, at least for now&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2010/08/02/weekend-server-upgrade-update/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Weekend Server Upgrade</title>
		<link>http://www.kerrywong.com/2010/08/01/weekend-server-upgrade/</link>
		<comments>http://www.kerrywong.com/2010/08/01/weekend-server-upgrade/#comments</comments>
		<pubDate>Sun, 01 Aug 2010 23:47:59 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Linux/BSD]]></category>
		<category><![CDATA[Miscellaneous]]></category>
		<category><![CDATA[Ubuntu 10.04 Server]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=2407</guid>
		<description><![CDATA[I have finally got around to upgrade my web server. The server I have been using was an old Pentium III about 10 years old. It had been serving my website quite well over the years till recently. Due to the small amount of RAM (512MB), that server was no longer able to handle the [...]]]></description>
			<content:encoded><![CDATA[<p>I have finally got around to upgrade my web server. The server I have been using was an old Pentium III about 10 years old. It had been serving my website quite well over the years till recently. <span id="more-2407"></span>Due to the small amount of RAM (512MB), that server was no longer able to handle the ever increasing net traffic and had been crashing with out-of-memory errors quite often.</p>
<p>Luckily, I got a fully equipped hand-me-down Compaq (HP) ProLiant DL360 G2 server and I decided to migrate my website over during the weekend.</p>
<p>Even though this server is a few generations behind, it has dual Pentium III S 1.4 GHz processors, 15,000 RMP SCSI harddrive and 4GB of RAM which is more than plenty to meet my near future needs.</p>
<p>Since my web server was running on Ubuntu Server 8.04, this hardware upgrade also gives me an opportunity to upgrade the OS to the latest version of Ubuntu Server (10.04) which is also an LTS version. </p>
<p>With the new hardware and software, the site should be running rather smoothly for the next couple of years&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2010/08/01/weekend-server-upgrade/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>An Arduino Compatible Using CP2102</title>
		<link>http://www.kerrywong.com/2010/07/16/an-arduino-compatible-using-cp2102/</link>
		<comments>http://www.kerrywong.com/2010/07/16/an-arduino-compatible-using-cp2102/#comments</comments>
		<pubDate>Sat, 17 Jul 2010 00:30:55 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[AVR/Arduino]]></category>
		<category><![CDATA[Arduino]]></category>
		<category><![CDATA[CP210x]]></category>
		<category><![CDATA[UART]]></category>
		<category><![CDATA[USB]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=2378</guid>
		<description><![CDATA[Standard Arduino boards use FTDI&#8217;s FT232RL to interface with computer&#8217;s USB port. Since FT232R is just a USB to UART converter, it is possible to build an Arduino compatible USB interface using other USB to UART chips. One such alternative is Silicon Labs&#8216; CP2102. I particularly like this USB to UART transceiver because very few [...]]]></description>
			<content:encoded><![CDATA[<p>Standard <a href="http://www.arduino.cc">Arduino</a> boards use FTDI&#8217;s <a href="http://www.ftdichip.com/Products/FT232R.htm">FT232RL</a> to interface with computer&#8217;s USB port. Since FT232R is just a USB to UART converter, it is possible to build an Arduino compatible USB interface using other USB to UART chips.<span id="more-2378"></span></p>
<p>One such alternative is <a href="http://www.silabs.com/">Silicon Labs</a>&#8216; <a href="www.silabs.com/Support%20Documents/TechnicalDocs/cp2102.pdf">CP2102</a>. I particularly like this USB to UART transceiver because very few extra components are required for it to work. As an added benefit, this chip is also cheaper than the ubiquitous FT232R. Of course, there are also a few trade offs. First of all,  CP2102 does not provide a bit bang interface (the X3 pins on the Arduino board on the other hand can be used for bit bang operations, but the X3 pins are not soldered with header pins by default and thus for the average users no bit bang support should not be an issue). Secondly, CP2102 does not have the configurable general purpose I/O pins to drive the TX/RX LEDs. There are other minor differences as well (for instance the maximum transmission speed for FT232R is 3Mbps while CP2102 tops at 1Mbps. Both chips are more than adequate for the maximum 115,200 baud rate supported in Arduino environment), but they do not affect the performance in our application of interfacing with Arduino.</p>
<p>Here is the schematics for using CP2102 with ATmega328p (the circuit below is compatible with the Arduino IDE):</p>
<div id="attachment_2384" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/07/CP2102_ArduinoSch.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/07/CP2102_ArduinoSch-300x164.png" alt="Arduino using CP2102" title="Arduino using CP2102" width="300" height="164" class="size-medium wp-image-2384" /></a><p class="wp-caption-text">Arduino using CP2102</p></div>
<p>if you compare the above circuit with the official <a href="http://arduino.cc/en/uploads/Main/arduino-duemilanove-schematic.pdf">Arduino Duemilanove board</a> you will see that the interfacing portions (RXD, TXD and TDR) are virtually identical.</p>
<p>Since CP2102 comes only in QFN-28 packaging, some people might find it slightly harder to deal with than TSSOP. Using the <a href="how http://www.kerrywong.com/2010/04/16/interfacing-lis3lv02dl-using-spi-i/">prototyping method</a> I mentioned a few months back though, it is fairly straightforward to use the chip on a standard perf-board nevertheless. No special tools or stencils are needed. The following picture shows the USB to UART converter portion of the Arduino, which can be used to replace the FT232 break out board. I chose to break out the converter so that I could use it in other projects that require serial connections.</p>
<div id="attachment_2382" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/07/CP2102USBtoSerial.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/07/CP2102USBtoSerial-300x225.jpg" alt="USB to Serial Board based on CP2102" title="USB to Serial Board based on CP2102" width="300" height="225" class="size-medium wp-image-2382" /></a><p class="wp-caption-text">USB to Serial Board based on CP2102</p></div>
<p>If you are running Linux, you do not need any third-party device drivers. All recent Linux kernels support CP210x via the usbserial kernel module. Once connected, you should be able to use <i>dmesg</i> and see these messages:</p>
<blockquote><p>
[ 8333.572512] usb 8-2: new full speed USB device using uhci_hcd and address 3<br />
[ 8333.744748] usb 8-2: configuration #1 chosen from 1 choice<br />
[ 8333.785114] usbcore: registered new interface driver usbserial<br />
[ 8333.785161] USB Serial support registered for generic<br />
[ 8333.785221] usbcore: registered new interface driver usbserial_generic<br />
[ 8333.785222] usbserial: USB Serial Driver core<br />
[ 8333.792419] USB Serial support registered for cp210x<br />
[ 8333.792460] cp210x 8-2:1.0: cp210x converter detected<br />
[ 8333.920011] usb 8-2: reset full speed USB device using uhci_hcd and address 3<br />
[ 8334.076745] usb 8-2: cp210x converter now attached to ttyUSB0<br />
[ 8334.076760] usbcore: registered new interface driver cp210x<br />
[ 8334.076762] cp210x: v0.09:Silicon Labs CP210x RS232 serial adaptor driver
</p></blockquote>
<p>If you are running Windows, you will need to install the <a href="http://www.silabs.com/products/mcu/Pages/SoftwareDownloads.aspx">royalty-free driver</a> from Silicon Labs directly.</p>
<p>Under Linux, CP210x shows up as a a ttyUSB device. You can use the Arduino IDE to program your ATmega328p&#8217;s just as you would with an official Arduino. Serial communication via the serial monitor works the same way as well. Like the official Arduino, the above circuit also automatically resets whenever you upload a program.</p>
<p>The following picture shows this Arduino compatible circuit in action.</p>
<div id="attachment_2386" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/07/CP2102Arduino.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/07/CP2102Arduino-300x225.jpg" alt="An Arduino Compatible Using CP2102" title="An Arduino Compatible Using CP2102" width="300" height="225" class="size-medium wp-image-2386" /></a><p class="wp-caption-text">An Arduino Compatible Using CP2102</p></div>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2010/07/16/an-arduino-compatible-using-cp2102/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Clock Synchronization Via I2C (TWI)</title>
		<link>http://www.kerrywong.com/2010/07/10/clock-synchronization-via-i2c-twi/</link>
		<comments>http://www.kerrywong.com/2010/07/10/clock-synchronization-via-i2c-twi/#comments</comments>
		<pubDate>Sat, 10 Jul 2010 15:40:29 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[AVR/Arduino]]></category>
		<category><![CDATA[Arduino]]></category>
		<category><![CDATA[Atmega328P]]></category>
		<category><![CDATA[BQ3287]]></category>
		<category><![CDATA[I2C]]></category>
		<category><![CDATA[TWI]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=2306</guid>
		<description><![CDATA[When I was doing the clock/stop watch project last month, I mentioned that I intended to add I2C (TWI) communication functionality so that I could get time from this clock and use it as timer signal to control other electronics. The reason I mentioned back then for going this route was that I did not [...]]]></description>
			<content:encoded><![CDATA[<p>When I was doing<a href="http://www.kerrywong.com/2010/06/05/a-clock-stop-watch-based-on-bq3287/"> the clock/stop watch</a> project last month, I mentioned that I intended to add <a href="http://en.wikipedia.org/wiki/I%C2%B2C">I2C (TWI</a>) communication functionality so that I could get time from this clock and use it as timer signal to control other electronics. <span id="more-2306"></span></p>
<p>The reason I mentioned back then for going this route was that I did not have enough I/O pins since bq3287 used most of the pins on ATmega328p. Of couse, I could&#8217;ve just used a serial real-time clock like <a href="http://datasheets.maxim-ic.com/en/ds/DS1307.pdf">DS1307</a> and thus free up the pins, but I thought it would be a cool idea to experiment with bidirectional I2C communications. A key benefit of using I2C is that only three wires are required between the two <a href="http://en.wikipedia.org/wiki/Microcontroller">MCU</a>s, which makes it possible to use standard two-conductor shielded wire commonly used in stereo earphones to serve as the communication link.</p>
<p>For those who are impatient, the full source code can be downloaded toward the end of this article.   </p>
<p>My main design goal was to achieve bi-directional communication between two ATmega328&#8242;s using I2C (TWI). Namely I wanted to be able to:</p>
<ul>
<li>transmit date/time information from the <a href="http://www.kerrywong.com/2010/06/05/a-clock-stop-watch-based-on-bq3287/">7seg LED clock</a> to the other MCU where time can be displayed on an LCD.</li>
<li>set date/time from the remote MCU and sync the date/time settings back to the main <a href="http://www.kerrywong.com/2010/06/05/a-clock-stop-watch-based-on-bq3287/">7seg LED clock</a>.</li>
</ul>
<p>At a high level, bidirectional communication using the <a href="http://www.arduino.cc/en/Reference/Wire">Arduino Wire library</a> can be achieved by assigning unique addresses to the devices that participate in the communication:</p>
<pre class="brush: cpp;">
//device 1
Wire.begin(ADDRESS_1);
Wire.beginTransmission(ADDRESS_2);
...
Wire.endTransmission();

//device 2
Wire.begin(ADDRESS_2);
Wire.beginTransmission(ADDRESS_1);
...
Wire.endTransmission();
</pre>
<p>In order to be able to send the time and date information between the two ATmega328p&#8217;s, I defined the structure <i>RTCMessage </i> as follows:</p>
<pre class="brush: cpp;">
struct RTCMessage {
    byte sender;
    byte msgType;
    byte year;
    byte month;
    byte day;
    byte hour;
    byte minute;
    byte secondInd;
    byte dayOfWeek;
};
</pre>
<p>On the 7seg clock side (where the RTC chip bq3287 is located), the Wire library is initialized to be a host on address 5 and listens on address 4. The event handler function <i>receiveEvent</i> processes the incoming date/time data and adjust the RTC settings accordingly. In the main loop, the current date/time info is sent to the other ATmega328p (address 4, ADDR_TWI_REMOTE) constantly so that the two clocks can keep in sync.</p>
<pre class="brush: cpp;">
const int ADDR_TWI_LOCAL = 5;
const int ADDR_TWI_REMOTE = 4;

 //... ... code omitted here ... ...

void setup() {

    //... ... code omitted here ... ...

    Wire.begin(ADDR_TWI_LOCAL);
    Wire.onReceive(receiveEvent);
}

void receiveEvent(int howMany) {
    RTCMessage msg;

    msg.sender = Wire.receive();
    msg.msgType = Wire.receive();
    msg.year = Wire.receive();
    msg.month = Wire.receive();
    msg.day = Wire.receive();
    msg.hour = Wire.receive();
    msg.minute = Wire.receive();
    msg.secondInd = Wire.receive();
    msg.dayOfWeek = Wire.receive();

    adjust(ADDR_CUR_YEAR, msg.year);
    adjust(ADDR_CUR_MON, msg.month);
    adjust(ADDR_CUR_DAY, msg.day);
    adjust(ADDR_CUR_HOUR, msg.hour);
    adjust(ADDR_CUR_MIN, msg.minute);
    adjust(ADDR_CUR_DOW, msg.dayOfWeek);
}

void loop() {

    //... ... code omitted here ... ...

    RTCMessage message;

    message.day = curDay;
    message.dayOfWeek = curDOW;
    message.hour = curHour;
    message.minute = curMin;
    message.month = curMonth;
    message.year = curYear;
    message.msgType = MsgGetTime;
    message.sender = ADDR_TWI_LOCAL;
    message.secondInd = secondIndLEDOn ? 1 : 0;

    Wire.beginTransmission(ADDR_TWI_REMOTE);

    Wire.send(message.sender);
    Wire.send(message.msgType);
    Wire.send(message.year);
    Wire.send(message.month);
    Wire.send(message.day);
    Wire.send(message.hour);
    Wire.send(message.minute);
    Wire.send(message.secondInd);
    Wire.send(message.dayOfWeek);

    Wire.endTransmission();
}
</pre>
<p>The code on the other ATmega328p is slightly more complex but the idea is essentially the same. We first set up the master and slave address for TWI communication. Note that the master/slave addresses we set up here are the opposite compared to those we did on the RTC clock side.</p>
<p>Here is the code snippet relevant to the TWI communication on the LCD display side:</p>
<pre class="brush: cpp;">
const int ADDR_TWI_LOCAL = 4;
const int ADDR_TWI_REMOTE = 5;

 //... ... code omitted here ... ...

void setup() {

    //... ... code omitted here ... ...

    Wire.begin(ADDR_TWI_LOCAL);
    Wire.onReceive(receiveEvent);

}

void receiveEvent(int howMany) {
    intProc = true;

    message.sender = Wire.receive();
    message.msgType = Wire.receive();
    message.year = Wire.receive();
    message.month = Wire.receive();
    message.day = Wire.receive();
    message.hour = Wire.receive();
    message.minute = Wire.receive();
    message.secondInd = Wire.receive();
    message.dayOfWeek = Wire.receive();

    if (currentMode == MODE_TIME_SETUP || currentMode == MODE_NORMAL_CANCEL) {
        displayTime();
    } else if (currentMode &gt;= MODE_ALARM_SETUP) {
        displayAlarm(currentMode - MODE_ALARM_SETUP);
    }

    intProc = false;
}

void saveTimeSettings() {
    Wire.beginTransmission(ADDR_TWI_REMOTE);
    Wire.send(messageCopy.sender);
    Wire.send(messageCopy.msgType);
    Wire.send(messageCopy.year);
    Wire.send(messageCopy.month);
    Wire.send(messageCopy.day);
    Wire.send(messageCopy.hour);
    Wire.send(messageCopy.minute);
    Wire.send(messageCopy.secondInd);
    Wire.send(messageCopy.dayOfWeek);
    Wire.endTransmission();

    message = messageCopy;
}

void loop() {
    //process button pressed events
    for (int i = 0; i &lt; NUM_OF_BUTTONS; i++) {
        if (buttonPressed(i)) {
            if (intProc) return;
            cli();

            lcd.setCursor(15, 1);
            lcd.print(&quot; &quot;);

            if (i == BTN_MODE_SELECT) {
                currentMode++;
                renderCurrentMode();
            } else if (i == BTN_CURSOR_CTRL) {
                if (currentMode == MODE_TIME_SETUP) {
                    renderTimeSetup();
                } else if (currentMode &gt;= MODE_ALARM_SETUP) {
                    renderAlarmSetup();
                }
            } else if (i == BTN_UP || i == BTN_DOWN) {
                if (currentMode == MODE_TIME_SETUP) {
                    adjustTimeSetup(i);
                } else if (currentMode &gt;= MODE_ALARM_SETUP) {
                    adjustAlarmSetup(i);
                }
            } else if (i == BTN_ENTER) {
                if (currentMode == MODE_TIME_SETUP) {
                    sei();
                    saveTimeSettings();
                    cli();
                    lcd.setCursor(15, 1);
                    lcd.write(SAVED_SYM);
                } else if (currentMode &gt;= MODE_ALARM_SETUP) {
                    saveAlarmSettings(currentMode - MODE_ALARM_SETUP);
                    lcd.setCursor(15, 1);
                    lcd.write(SAVED_SYM);
                } else if (currentMode == MODE_NORMAL_CANCEL) {
                    backLight = !backLight;

                    if (backLight) digitalWrite(PIN_BACKLIGHT, HIGH);
                    else digitalWrite(PIN_BACKLIGHT, LOW);
                }
            }
            sei();
        }

        if (buttonRleased(i)) {
            //the button is released, no action is necessary.
        }
    }

    checkAlarms();
}
</pre>
<p>The LCD side has five buttons, which are used to set/navigate time and alarm settings (you can download the full source code below). The information displayed on the LCD changes depending on the modes these buttons are in. This aside, the general idea is that whenever the date/time information is transmitted from the remote 7seg RTC clock, it is displayed on the LCD via <i>displayTime</i> if the current mode is set to display time.  </p>
<p>When the date/time settings are changed on the LCD side, it is saved back to the RTC clock via <i>saveTimeSettings</i> in the main loop. Note that the interrupts are disabled for most of the loop via <i>cli</i> except for syncing the date/time settings. This is necessary to ensure that the button selections are fully processed before any interrupt handling occurs. If this is not done, the output on the LCD would be garbled as the TWI interrupt might happen during a screen update.</p>
<p>The following picture shows how the LCD (in the front) and the 7seg clock are in sync with the I2C primitives shown above.</p>
<div id="attachment_2319" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/07/i2cclock.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/07/i2cclock-300x225.jpg" alt="Clock Synchronization Via I2C" title="Clock Synchronization Via I2C" width="300" height="225" class="size-medium wp-image-2319" /></a><p class="wp-caption-text">Clock Synchronization Via I2C</p></div>
<p>The alarm settings are stored in the EEPROM of the ATmega328p on the LCD side which are compared against the current time stamp in <i>checkAlarms</i> to determine whether the alarm conditions are met.</p>
<p>The full source code for this project can be downloaded here (note, I used NetBeans IDE to create these projects. Please refer to <a href="http://www.kerrywong.com/2010/05/16/arduino-development-using-netbeans/">this post</a> to see how it is done):</p>
<p>The 7seg Digital Clock: <a href='http://www.kerrywong.com/blog/wp-content/uploads/2010/07/DigitalClock.tar.gz'>DigitalClock.tar</a><br />
The LCD Controller: <a href='http://www.kerrywong.com/blog/wp-content/uploads/2010/07/LCD.tar.gz'>LCD.tar</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2010/07/10/clock-synchronization-via-i2c-twi/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Case For Using Parallel Programmer</title>
		<link>http://www.kerrywong.com/2010/06/26/the-case-for-using-parallel-programmer/</link>
		<comments>http://www.kerrywong.com/2010/06/26/the-case-for-using-parallel-programmer/#comments</comments>
		<pubDate>Sat, 26 Jun 2010 17:37:58 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[AVR/Arduino]]></category>
		<category><![CDATA[Miscellaneous]]></category>
		<category><![CDATA[Atmega328P]]></category>
		<category><![CDATA[Parallel Programmer]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=2267</guid>
		<description><![CDATA[This is what I ran into for the first time: I was flashing the chip the other day and after many successful runs I encountered the following infamous avrdude error: &#8230; &#8230; &#8230; avrdude: Device signature = 0×000000 &#8230; &#8230; &#8230; Typically when I ran into this problem it was due to loose cable connection [...]]]></description>
			<content:encoded><![CDATA[<p>This is what I ran into for the first time: I was flashing the chip the other day and after many successful runs I encountered the following infamous avrdude error:<span id="more-2267"></span></p>
<blockquote><p>
&#8230; &#8230; &#8230;<br />
avrdude: Device signature = 0×000000<br />
&#8230; &#8230; &#8230;
</p></blockquote>
<p>Typically when I ran into this problem it was due to loose cable connection and I was able to get past it by reconnecting the ICSP header and try again. But this time, the it seems that no matter how many times I tried the problem remained.</p>
<p>I am pretty sure that chip itself was not damaged as it was sitting in the <a href="http://www.kerrywong.com/2010/04/24/an-arduino-icsp-board/">ICSP board I built</a> all the time and I was able to program it successfully many times minutes before this happened. </p>
<p>Here&#8217;s what I have tried and so far had no success:</p>
<ul>
<li>rebooted system</li>
<li>re-seated the IC
<li>changed -B option to allow more delays</li>
<li>changed -b option to different baud rates</li>
<li>tried to use external clock signal from a working ATmega328p</li>
</ul>
<p>And just to be sure nothing was wrong with either the cable or the board itself, I popped in another ATmega328P and everything worked.  So it seems that even though I did not change any fuse settings, and the only command I used was </p>
<blockquote><p>avrdude -V -F -C avrdude.conf -c duemilanove -p m328p -U flash:w:{hex file})</p></blockquote>
<p>I guess that somehow the fuse settings had changed and thus the chip stopped responding to the clock signal.</p>
<p>So, it&#8217;s time for me to try the high voltage parallel programming method (like <a href="http://mightyohm.com/blog/products/avr-hv-rescue-shield/">this one</a>) to see if my theory was correct. </p>
<p>Following the <a href="http://mightyohm.com/blog/products/avr-hv-rescue-shield/">instructions</a>, I built the shield quickly (not very pretty but serves the purpose nevertheless). The none-standard header spacing was not a big issue as it was easy enough to bend the header pins to achieve the desired spacing (see picture below):</p>
<div id="attachment_2282" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/06/shield1.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/06/shield1-300x225.jpg" alt="Top view" title="Top view" width="300" height="225" class="size-medium wp-image-2282" /></a><p class="wp-caption-text">Top view</p></div>
<div id="attachment_2283" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/06/shield2.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/06/shield2-300x221.jpg" alt="Bottom View" title="Bottom View" width="300" height="221" class="size-medium wp-image-2283" /></a><p class="wp-caption-text">Bottom View</p></div>
<p>For the high voltage programming enable 12V supply, I chose to use a simply transistor switch instead of the boost converter:</p>
<div id="attachment_2286" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/06/HVEnable.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/06/HVEnable-300x232.png" alt="12V Supply" title="12V Supply" width="300" height="232" class="size-medium wp-image-2286" /></a><p class="wp-caption-text">12V Supply</p></div>
<p>The drawback of this approach is that the output voltage is not as precise and I had to experiment a little bit to obtain the required HV programming voltage The enable signal comes from the Arduino is around 4.5 V which may not be sufficient to put the transistor in the saturated mode and in my case with a 14 Volt supply, I was able to obtain the required 12 V output. Since the control signal is inverted compared to the original schematic in the article, I had to invert all the digitalWrites to the 12V enable pin to make the program work with my version of the shield.</p>
<p>I used the <a href="http://www.engbedded.com/fusecalc/">AVR Fuse calculator</a> to obtain the default fuse settings for ATmega328p:</p>
<blockquote><p>
LFuse = 0&#215;62<br />
HFuse = 0xD9<br />
EFuse = 0xFF
</p></blockquote>
<p> And it brought the &#8220;bricked&#8221; ATmega328p back to life with the first try! So I guess a parallel mode programmer can come in handy in situations like this. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2010/06/26/the-case-for-using-parallel-programmer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Invoking DS89C430/450 ROM Loader Using Arduino</title>
		<link>http://www.kerrywong.com/2010/06/13/invoking-ds89c430-45-rom-loader-using-arduino/</link>
		<comments>http://www.kerrywong.com/2010/06/13/invoking-ds89c430-45-rom-loader-using-arduino/#comments</comments>
		<pubDate>Sun, 13 Jun 2010 23:24:53 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[AVR/Arduino]]></category>
		<category><![CDATA[Arduino]]></category>
		<category><![CDATA[Baud Rate Crystal Frequency Calculator]]></category>
		<category><![CDATA[DS89C430]]></category>
		<category><![CDATA[DS89C450]]></category>
		<category><![CDATA[ROM Loader]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=2214</guid>
		<description><![CDATA[DS89C430 and DS89C450 are two ultra-high-speed 8051-compatible microcontrollers from Maxim Integrated Products. One unique feature of DS89C430/450 microcontroller is that it has a ROM loader mode which can be used to program the microcontroller itself. According to the user&#8217;s guide, UART0 (pin 10 and pin 11) is invoked in ROM loader mode when RST is [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://datasheets.maxim-ic.com/en/ds/DS89C430-DS89C450.pdf">DS89C430 and DS89C450</a> are two ultra-high-speed 8051-compatible microcontrollers from <a href="http://www.maxim-ic.com/">Maxim Integrated Products</a>. One unique feature of DS89C430/450 microcontroller is that it has a ROM loader mode which can be used to program the microcontroller itself.<span id="more-2214"></span></p>
<p>According to the <a href="http://www.maxim-ic.com/products/microcontrollers/pdfs/DS89C430_User_Guide.pdf">user&#8217;s guide</a>, UART0 (pin 10 and pin 11) is invoked in ROM loader mode when RST is set to High and both EA and PSEN are set to LOW simultaneously. After the ROM loader mode is enabled, serial communication can be handled between a PC&#8217;s <a href="http://en.wikipedia.org/wiki/RS-232">RS-232</a> port and the microcontroller using a RS-232 transmitter/receiver such as <a href="http://datasheets.maxim-ic.com/en/ds/DS232A.pdf">DS232A</a>.</p>
<p>It is also possible to communicate with DS89C430/450&#8242;s using PC&#8217;s USB port with a USB UART converter IC such as FTDI&#8217;s <a href="http://www.ftdichip.com/Products/FT232R.htm">FT232R</a>. If you have an <a href="http://www.arduino.cc">Arduino</a>, then you can just use the on-board FT232RL for this purpose. Technically speaking, this has little to do with Arduino as you could just use an FT232R adapter board, but with Arduino the RX/TX pins are readily accessible (pin 0 and pin 1) and thus using Arduino as a USB to UART converter couldn&#8217;t have been any easier. The basic schematic for using Arduino to invoke the DS89C430/450&#8242;s ROM loader mode is shown below:</p>
<div id="attachment_2220" class="wp-caption aligncenter" style="width: 226px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/06/ds89c430_romloader.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/06/ds89c430_romloader-216x300.png" alt="DS89C430/450" title="DS89C430/450" width="216" height="300" class="size-medium wp-image-2220" /></a><p class="wp-caption-text">DS89C430/450</p></div>
<p>Please note that DS89C430/450&#8242;s RX pin is connected to the socket on the Arduino board marked with RX and the TX pin is connected to the socket marked with TX. This is because Arduino&#8217;s RX socket is actually connected to the TX pin (pin 1) of FT232RL and TX socket is connected to the RX (pin 5) of FT232RL. The picture below shows how this is setup between an DS89C430 and Arduino (I used an external 5V supply here for the DS89C430 board, but you can use the 5V pin directly from the Arduino board if you want to).</p>
<div id="attachment_2224" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/06/Arduino_8051.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/06/Arduino_8051-300x225.jpg" alt="Connecting DS89C430 to Arduino" title="Connecting DS89C430 to Arduino" width="300" height="225" class="size-medium wp-image-2224" /></a><p class="wp-caption-text">Connecting DS89C430 to Arduino</p></div>
<p>According to the <a href="http://www.maxim-ic.com/products/microcontrollers/pdfs/DS89C430_User_Guide.pdf">user guide</a>, DS89C430/450&#8242;s ROM loader automatically tries baud rates generated by this equation:<br />
\[ROM Loader Baud Rate = \frac{Crystal Frequency}{192\times(256-Timer Reload)}\]</p>
<p>And the timer reload values attempted by the loader are: FF, FE, FD, FC, FB, FA, F8, F6, F5, F4, F3, F0, EC, EA, E8, E6, E0, DD, D8, D4, D0, CC, C0, BA, B0, A8, A0, 98, 80, 60, 40. In order for a given generated baud rate to work, the error between the generated baud rate and the UART&#8217;s baud rate must be less than 3%.</p>
<p>To make the selection of crystal frequency easier, I developed a spreadsheet that can be used to determine which standard baud rate a particular crystal can operate under. You can simply plugin the crystal frequency you intend to use and the supported baud rates are automatically highlighted in green (see screenshot below).</p>
<div id="attachment_2241" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/06/crystal-frequency-calculation.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/06/crystal-frequency-calculation-300x128.jpg" alt="Baud Rate, Crystal Frequency Calculation" title="Baud Rate, Crystal Frequency Calculation" width="300" height="128" class="size-medium wp-image-2241" /></a><p class="wp-caption-text">Baud Rate, Crystal Frequency Calculation</p></div>
<p>This spreadsheet can be downloaded here:<br />
<a href='http://www.kerrywong.com/blog/wp-content/uploads/2010/06/baudratecalc.ods'>baudratecalc.ods (OpenOffice)</a><br />
<a href='http://www.kerrywong.com/blog/wp-content/uploads/2010/06/baudratecalc.xls'>baudratecalc.xls (Excel)</a></p>
<p>The crystal frequency I used is 21.7 Mhz which as you can see in the screenshot above supports most of the standard baud rates. </p>
<p>I use PuTTY for the serial communication with the following parameters (note the speed must be one of the supported baud rate calculated above, it depends on the crystal you use). You can use gtkterm as well.</p>
<blockquote><p>
Serial line to connect to: /dev/ttyUSB0<br />
Speed: 115200<br />
Data bits: 8<br />
Stop bits: 1<br />
Parity: None<br />
Flow control: None
</p></blockquote>
<p>And here&#8217;s a screen shot of DS89C430 in ROM loader mode:</p>
<div id="attachment_2225" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/06/8051_putty.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/06/8051_putty-300x207.png" alt="DS89C430 ROM loader" title="DS89C430 ROM loader" width="300" height="207" class="size-medium wp-image-2225" /></a><p class="wp-caption-text">DS89C430 ROM loader</p></div>
<p>When the microcontroller is in ROM loader mode, programs can be uploaded using the ROM loader command interface mentioned in the <a href="http://www.maxim-ic.com/products/microcontrollers/pdfs/DS89C430_User_Guide.pdf">user guide</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2010/06/13/invoking-ds89c430-45-rom-loader-using-arduino/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Clock/Stop Watch Based on BQ3287</title>
		<link>http://www.kerrywong.com/2010/06/05/a-clock-stop-watch-based-on-bq3287/</link>
		<comments>http://www.kerrywong.com/2010/06/05/a-clock-stop-watch-based-on-bq3287/#comments</comments>
		<pubDate>Sat, 05 Jun 2010 17:07:33 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[AVR/Arduino]]></category>
		<category><![CDATA[Atmega328P]]></category>
		<category><![CDATA[BQ3287]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[I2C]]></category>
		<category><![CDATA[RTC]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=2157</guid>
		<description><![CDATA[Over the past couple of weeks, I have been experimenting with BQ3287, a real time clock module from Taxes Instruments. My ultimate goal was to eventually create a full fledged control platform based on this RTC module (more on this later). But first and foremost, I would like to explore its capabilities as an accurate [...]]]></description>
			<content:encoded><![CDATA[<p>Over the past couple of weeks, I have been experimenting with <a href="http://focus.ti.com/lit/ds/symlink/bq3287.pdf">BQ3287</a>, a real time clock module from <a href="http://www.ti.com">Taxes Instruments</a>. My ultimate goal was to eventually create a full fledged control platform based on this RTC module (more on this later). But first and foremost, I would like to explore its capabilities as an accurate time keeper.<span id="more-2157"></span></p>
<p>The BQ3287 model by itself is really easy to interface with MCUs. There is a nice <a href="http://fritzing.org/projects/ibm-rtc-on-arduino/">tutorial</a> on how to use BQ3287 with <a href="http://www.arduino.cc">Arduino</a> and some of the code I am using in this post is borrowed from that project. The main difficulty of turning BQ3287 into a full-fledged clock is that this RTC module uses up to 16 digital pins out of 20 usable pins an ATMega328p has, which leaves very few pins for display and control purposes. After toying with a few possible designs, I decided to use 13 out of the 16 pins so that no major functionality is sacrificed (MOT is left disconnected using Intel bus timing, RESET is tied to Vcc and CS is connected to ground).</p>
<p>Digital pin 0 and 1 (chip pin 1 and 2) are used for button input. Since these two pins are also used as serial RX TX pair when used with the Arduino (the FT232RL chip communicates to The ATmega328 via these two pins) board, I resorted to the <a href="http://www.kerrywong.com/2010/04/24/an-arduino-icsp-board/">ICSP method</a> to program the chip without using the Arduino board. </p>
<p>With this setup, we have two additional pins (pin 27 and 28, these are analog pin 4 and 5 on the Arduino board) available. Since these two pin s are the SCL and SDA pins in <a href="http://en.wikipedia.org/wiki/I%C2%B2C">TWI (I2C)</a> communication, I am planning to use them to communicate to another ATmega328 chip to further expand the functionality of this clock in the future.</p>
<p>For now, I am using the two buttons to multiplex the following functions:</p>
<ul>
<li>Display Time </li>
<li>Display Date </li>
<li>Display Year</li>
<li>Stop Watch</li>
<li>Change Time Setting</li>
<li>Change Date Setting</li>
<li>Change Year Setting</li>
</ul>
<p>Please see the comment in the code section below to see how these functionalities are achieved.</p>
<p>Three pins are used to control the <a href="http://www.kerrywong.com/2010/04/10/4-digit-7-segment-display-using-arduino/">4 7 segment display I made earlier</a>. The display update is triggered by the interrupt signal generated from the SQW output pin of BQ3287, I set the interrupt frequency to 128 Hz (RS3 RS2 RS1 RS0 = 1001) to ensure the accuracy of the stop watch (0.1 second) while still maintain a reasonable overhead. The update code all resides in the interrupt handler (intr()).</p>
<p>As you can see in the code, dot between the hour and minute display is turned on and off on a half second interval and in change settings mode the values to be changed also flashes at a half second interval.</p>
<p>Here are some pictures showing the clock displaying in various modes. And the last picture shows the board setup: the front board houses the 4 7 segment display, the left side is the ATmega328 board, the middle one contains the BQ3287 module and the right side board is the voltage regulator board. I used a Taxes Instrument <a href="http://focus.ti.com/general/docs/lit/getliterature.tsp?genericPartNumber=tl720m05-q1&#038;fileType=pdf">TL720M05 LDO linear voltage regulator</a>, which is a nice LDO pin compatible replacement of the good old 7805.</p>
<table>
<tr>
<td><div id="attachment_2161" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/06/7seg_1.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/06/7seg_1-300x225.jpg" alt="Time" title="Time" width="300" height="225" class="size-medium wp-image-2161" /></a><p class="wp-caption-text">Time</p></div></td>
<td><div id="attachment_2162" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/06/7seg_2.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/06/7seg_2-300x225.jpg" alt="Date" title="Date" width="300" height="225" class="size-medium wp-image-2162" /></a><p class="wp-caption-text">Date</p></div></td>
</tr>
<tr>
<td><div id="attachment_2168" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/06/7seg_3.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/06/7seg_3-300x225.jpg" alt="Year" title="Year" width="300" height="225" class="size-medium wp-image-2168" /></a><p class="wp-caption-text">Year</p></div></td>
<td><div id="attachment_2170" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/06/7seg_4.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/06/7seg_4-300x225.jpg" alt="Day of the Week (Thursday)" title="Day of the Week (Thursday)" width="300" height="225" class="size-medium wp-image-2170" /></a><p class="wp-caption-text">Day of the Week (Thursday)</p></div></td>
</tr>
<tr>
<td><div id="attachment_2173" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/06/7seg_5.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/06/7seg_5-300x225.jpg" alt="Stop Watch" title="Stop Watch" width="300" height="225" class="size-medium wp-image-2173" /></a><p class="wp-caption-text">Stop Watch</p></div></td>
<td><div id="attachment_2174" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/06/7seg_6.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/06/7seg_6-300x225.jpg" alt="The Setup" title="The Setup" width="300" height="225" class="size-medium wp-image-2174" /></a><p class="wp-caption-text">The Setup</p></div></td>
</tr>
</table>
<p>And here&#8217;s the code listing for this project. As mentioned earlier, I am planing to use a separate ATmega328 board to communicate with this clock using TWI so that I can setup timers/alarms to control other electronics.</p>
<pre class="brush: cpp;">
//define the bidirectional address-data bus
const int ad0 = 3; //chip pin 5
const int ad1 = 4; //chip pin 6
const int ad2 = 5; //chip pin 11
const int ad3 = 6; //chip pin 12
const int ad4 = 7; //chip pin 13
const int ad5 = 8; //chip pin 14
const int ad6 = 9; //chip pin 15
const int ad7 = 10; //chip pin 16

//ALE or address strobe (AS pin)
const int as = 11; //chip pin 17
//WR or (RW pin)
const int rw = 12; //chip pin 18
//RD or OE (DS pin )
const int ds = 13; //chip pin 19
//interrupt request
const int irq = 14; //chip pin 23

//7-seg display pins
const int clockPin = 15; //chip pin 24
const int latchPin = 16; //chip pin 25
const int dataPin = 17; //chip pin 26

//control button pins
//Note, since these are the rx/tx pins when using FT232RL
//you will either have to program the chip using a programmer (the method I used)
//or using the remaining two two analog data pins (18 and 19). But then you are
//lossing two pins to work with.
const int btnPin1 = 0; //chip pin 1
const int btnPin2 = 1; //chip pin 2

const int COMMON_ANODE = 1; //1 CA, 0 CC

//bq3287 registers
const int regA = 0x0A;
const int regB = 0x0B;

//RO registers C,D
const int regC = 0x0C;
const int regD = 0x0D;

const int ADDR_CUR_SEC = 0;
const int ADDR_ALM_SEC = 1;
const int ADDR_CUR_MIN = 2;
const int ADDR_ALM_MIN = 3;
const int ADDR_CUR_HOUR = 4;
const int ADDR_ALM_HOUR = 5;
const int ADDR_CUR_DOW = 6;
const int ADDR_CUR_DAY = 7;
const int ADDR_CUR_MON = 8;
const int ADDR_CUR_YEAR = 9;

//display modes
//button 1 has 4 modes
const int DM_TIME = 0; //display time
const int DM_DATE = 1; //display date
const int DM_YEAR = 2; //display year
const int DM_DOW = 3; //display day of the week
const int DM_STOP_WATCH = 4; //display stop watch

//button 2 has 7 modes
const int DM_ADJ_NONE = 0; //display the current time
const int DM_ADJ_HOUR = 1; //adjust hour
const int DM_ADJ_MIN = 2; //adjust minute
const int DM_ADJ_MONTH = 3; //adjust month
const int DM_ADJ_DAY = 4; //adjust day
const int DM_ADJ_YEAR = 5; //adjust year
const int DM_ADJ_DOW = 6; //adjust day of the week

/** global variables for storing button's current mode.
 * Button functions
 * When button 2 is not pressed (in DM_ADJ_NONE)
 * press button 1 will cycle through the following display modes:
 *      current time (default)
 *      current date
 *      current year
 *      stop watch
 * when in stop watch mode, button 1 is used to start/stop/reset the stop watch.
 *
 * while in display current time mode (button 1 mode equals DM_TIME)
 * press button 2 will cycle through the following adjustment modes:
 *      adjust hour
 *      adjust minute
 *      adjust month
 *      adjust day
 *      adjust year
 *      adjust day of week
 * when in adjustment mode, button 1 is used to increment the settings.
 */
int btnMode1 = 0;
int btnMode2 = 0;

boolean btn1Pressed = false;
boolean btn2Pressed = false;

//stop watch initialization indicator, if this is set to true
//the stop watch is stopped and displays 0.0
boolean stopWatchInit = true;
boolean stopWatchStarted = false;

/** 7seg character mapping char &lt;-&gt; code */
struct CharMap {
    char c;
    byte v;
};

//the length of the character map, it must match
//the cmap[] array lengh below
const int cmap_len = 41;

//defines the 7seg display characters
struct CharMap cmap[] = {
    {' ', 0},
    {'1', 96},
    {'2', 218},
    {'3', 242},
    {'4', 102},
    {'5', 182},
    {'6', 190},
    {'7', 224},
    {'8', 254},
    {'9', 246},
    {'0', 252},
    {'A', 238},
    {'b', 62},
    {'c', 26},
    {'C', 156},
    {'d', 122},
    {'e', 222},
    {'E', 158},
    {'F', 142},
    {'g', 246},
    {'H', 110},
    {'h', 46},
    {'I', 96},
    {'J', 120},
    {'L', 28},
    {'n', 42},
    {'o', 58},
    {'P', 206},
    {'q', 230},
    {'r', 10},
    {'S', 182},
    {'t', 30},
    {'u', 56},
    {'U', 124},
    {'y', 118},
    {'-', 2},
    {'~', 128},
    {'_', 16},
    {'.', 1},
    {'|', 108},
    {'=', 144}
};

//indicates whether the led on 7seg indicating the &quot;seconds&quot; is on
boolean secondIndLEDOn = false;

//arrays for date/time conversion
char hour[2], minute[2], seconds[6];
char year[2], month[2], day[2], dow[1];

//the 4 characters on the 7seg
char c1, c2, c3, c4;

//this counter is incremented whenever the SW output pin
//triggers the interrupt
int interruptConter = 0;

//this counter is used to keep track of time in stop watch mode
unsigned int stopWatchCounter = 0;

/** same as delay() but works with interrupts */
void delayMilliseconds(int ms) {
    for (int i = 0; i &lt; ms; i++) {
        delayMicroseconds(1000);
    }
}

/** get the display code for a character
/* it looks through the charactor map and find a match that corresponds to c
/* if no match is found, it returns 2 (corresponding to character '-') */
byte getCharDisplayCode(char c) {
    byte r = 2;

    for (int i = 0; i &lt; cmap_len; i++) {
        if (c == cmap[i].c) {
            r = cmap[i].v;
            break;
        }
    }

    return r;
}

/** initialize the display
/* when the 7seg display is initialized, display nothing */
void init7seg() {
    pinMode(latchPin, OUTPUT);
    pinMode(clockPin, OUTPUT);
    pinMode(dataPin, OUTPUT);

    disp(' ', false, ' ', false, ' ', false, ' ', false);
}

/** this essentially is the library function shiftOut, it can be customized if
/* it is needed.
/* it works with 74HC595 (serial in, parallel out) */
void shiftOut(uint8_t dataPin, uint8_t clockPin, byte val) {
    int i;

    for (i = 0; i &lt; 8; i++) {
        digitalWrite(dataPin, (val &amp; _BV(i)));
        digitalWrite(clockPin, HIGH);
        digitalWrite(clockPin, LOW);
    }
}

/* display the characters on the 7seg
/* the boolean value between characters indicates whether to light up the
/* decimal point */
void disp(char c1, boolean dot1, char c2, boolean dot2, char c3, boolean dot3, char c4, boolean dot4) {
    byte b1 = getCharDisplayCode(c1);
    byte b2 = getCharDisplayCode(c2);
    byte b3 = getCharDisplayCode(c3);
    byte b4 = getCharDisplayCode(c4);

    if (dot1 == true) b1 += 1;
    if (dot2 == true) b2 += 1;
    if (dot3 == true) b3 += 1;
    if (dot4 == true) b4 += 1;

    if (COMMON_ANODE == 1) {
        b1 = 255 - b1;
        b2 = 255 - b2;
        b3 = 255 - b3;
        b4 = 255 - b4;
    }

    digitalWrite(latchPin, LOW);

    shiftOut(dataPin, clockPin, b4);
    shiftOut(dataPin, clockPin, b3);
    shiftOut(dataPin, clockPin, b2);
    shiftOut(dataPin, clockPin, b1);

    digitalWrite(latchPin, HIGH);
}

/** convert a number (maximum 2 digita) to a character array
/* returning the length of the converted char array
/* this is used to convert hour/minutes into characters for display */
int convertToCharAarray(byte num, char *dest) {
    sprintf(dest, &quot;%d&quot;, num);

    if (num &lt; 10) return 1;
    else if (num &lt; 100 &amp;&amp; num &gt;= 10) return 2;
    else return -1;
}

/** displays the current time on 7seg,
/* the display mode is controlled by the states of the button states */
void dispCurrentTime() {
    if (!bitRead(readbyte(regA), 7)) {
        byte h = readbyte(ADDR_CUR_HOUR);
        byte m = readbyte(ADDR_CUR_MIN);

        byte l1 = convertToCharAarray(h, hour);
        byte l2 = convertToCharAarray(m, minute);

        if (l1 == 1) {
            c2 = ' ';
            c1 = hour[0];
        } else {
            c1 = hour[1];
            c2 = hour[0];
        }

        if (l2 == 1) {
            c4 = '0';
            c3 = minute[0];
        } else {
            c3 = minute[1];
            c4 = minute[0];
        }
    }

    disp(c2, false, c1, secondIndLEDOn, c4, false, c3, false);

    switch (btnMode2) {
        case DM_ADJ_NONE: //normal display mode, displays time
            disp(c2, false, c1, secondIndLEDOn, c4, false, c3, false);
            break;
        case DM_ADJ_HOUR: //if adjust hour, flash the hour digits
            if (secondIndLEDOn)
                disp(' ', false, ' ', true, c4, false, c3, false);
            else
                disp(c2, false, c1, true, c4, false, c3, false);
            break;
        case DM_ADJ_MIN: //if adjust minutes, flash the minute digits
            if (secondIndLEDOn)
                disp(c2, false, c1, true, ' ', false, ' ', false);
            else
                disp(c2, false, c1, true, c4, false, c3, false);
            break;
    }
}

/** displays in stop watch mode. */
void dispStopWatch() {
    for (int i = 0; i &lt; 5; i++) seconds[i] = ' ';

    int i = (int) (((float) (stopWatchCounter) / 128.0) * 10.0 + 0.5);
    sprintf(seconds, &quot;%6d&quot;, i);

    if (stopWatchInit) {
        disp(' ', false, ' ', false, '0', true, '0', false);
    } else {
        if (stopWatchCounter &lt; 128) { //less than 1 second, displays the leading 0
            disp(seconds[2], false, seconds[3], false, '0', true, seconds[5], false);
        } else {
            disp(seconds[2], false, seconds[3], false, seconds[4], true, seconds[5], false);
        }
    }
}

/** displays current date */
void dispCurrentDate() {
    if (!bitRead(readbyte(regA), 7)) {
        byte m = readbyte(ADDR_CUR_MON);
        byte d = readbyte(ADDR_CUR_DAY);

        byte l1 = convertToCharAarray(m, month);
        byte l2 = convertToCharAarray(d, day);

        if (l1 == 1) {
            c2 = ' ';
            c1 = month[0];
        } else {
            c1 = month[1];
            c2 = month[0];
        }

        if (l2 == 1) {
            c4 = '0';
            c3 = day[0];
        } else {
            c3 = day[1];
            c4 = day[0];
        }
    }

    switch (btnMode2) {
        case DM_ADJ_NONE: //normal display mode, displays date
            disp(c2, false, c1, true, c4, false, c3, false);
            break;
        case DM_ADJ_MONTH: //if adjust month, flash the month digits
            if (secondIndLEDOn)
                disp(' ', false, ' ', true, c4, false, c3, false);
            else
                disp(c2, false, c1, true, c4, false, c3, false);
            break;
        case DM_ADJ_DAY: //if adjust day, flash the day digits
            if (secondIndLEDOn)
                disp(c2, false, c1, true, ' ', false, ' ', false);
            else
                disp(c2, false, c1, true, c4, false, c3, false);
            break;
        default:
            break;
    }

}

/** displays the current year (e.g. 2010) */
void dispCurrentYear() {
    if (!bitRead(readbyte(regA), 7)) {
        byte y = readbyte(ADDR_CUR_YEAR);

        byte l1 = convertToCharAarray(y, year);

        c2 = '2';
        c1 = '0';

        if (l1 == 1) {
            c4 = '0';
            c3 = year[0];
        } else {
            c3 = year[1];
            c4 = year[0];
        }
    }

    switch (btnMode2) {
        case DM_ADJ_NONE:
            disp(c2, false, c1, false, c4, false, c3, false);
            break;
        case DM_ADJ_YEAR:
            if (secondIndLEDOn)
                disp(c2, false, c1, false, ' ', false, ' ', false);
            else
                disp(c2, false, c1, false, c4, false, c3, false);
            break;
        default:
            break;
    }

}

/** displays the day of the week (e.g. day1 for Monday) */
void dispDayOfWeek() {
    if (!bitRead(readbyte(regA), 7)) {
        byte d = readbyte(ADDR_CUR_DOW);

        convertToCharAarray(d, dow);
    }

    switch (btnMode2) {
        case DM_ADJ_NONE: //normal display mode
            disp('d', false, 'A', false, 'y', false, dow[0], false);
            break;
        case DM_ADJ_DOW: //if adjust day of the week, flash the digit
            if (secondIndLEDOn)
                disp('d', false, 'A', false, 'y', false, ' ', false);
            else
                disp('d', false, 'A', false, 'y', false, dow[0], false);
            break;
    }
}

/** set the clock bus mode
/* INPUT or OUTPUT */
void setClkBusMode(int mode) {
    pinMode(ad0, mode);
    pinMode(ad1, mode);
    pinMode(ad2, mode);
    pinMode(ad3, mode);
    pinMode(ad4, mode);
    pinMode(ad5, mode);
    pinMode(ad6, mode);
    pinMode(ad7, mode);
}

/** read a byte from address */
byte readbyte(byte address) {
    byte readb = 0;

    //set address pins to output
    setClkBusMode(OUTPUT);
    //start READ cycle
    digitalWrite(rw, HIGH);
    //prepare to set address on bus
    digitalWrite(ds, HIGH);
    //delayMicroseconds(1);
    //set ALE high, on fall address latches
    digitalWrite(as, HIGH);

    //set address on bus
    digitalWrite(ad0, bitRead(address, 0));
    digitalWrite(ad1, bitRead(address, 1));
    digitalWrite(ad2, bitRead(address, 2));
    digitalWrite(ad3, bitRead(address, 3));
    digitalWrite(ad4, bitRead(address, 4));
    digitalWrite(ad5, bitRead(address, 5));
    digitalWrite(ad6, bitRead(address, 6));
    digitalWrite(ad7, bitRead(address, 7));

    //set ALE low, latch address
    digitalWrite(as, LOW);
    setClkBusMode(INPUT);
    //finish address setting
    digitalWrite(ds, LOW);
    //wait for data from address
    //set bus for input
    //start reading data
    readb = digitalRead(ad0) | (digitalRead(ad1) &lt;&lt; 1) | (digitalRead(ad2) &lt;&lt; 2) | (digitalRead(ad3) &lt;&lt; 3) | (digitalRead(ad4) &lt;&lt; 4) | (digitalRead(ad5) &lt;&lt; 5) | (digitalRead(ad6) &lt;&lt; 6) | (digitalRead(ad7) &lt;&lt; 7);
    digitalWrite(ds, HIGH);

    return readb;
}

/** write a byte to address */
void writebyte(byte address, byte value) {
    //set address pins to output
    setClkBusMode(OUTPUT);
    //start READ cycle
    digitalWrite(rw, HIGH);
    //prepare to set address on bus
    digitalWrite(ds, HIGH);
    //set ALE high, on fall address latches
    digitalWrite(as, HIGH);
    //set address on bus
    digitalWrite(ad0, bitRead(address, 0));
    digitalWrite(ad1, bitRead(address, 1));
    digitalWrite(ad2, bitRead(address, 2));
    digitalWrite(ad3, bitRead(address, 3));
    digitalWrite(ad4, bitRead(address, 4));
    digitalWrite(ad5, bitRead(address, 5));
    digitalWrite(ad6, bitRead(address, 6));
    digitalWrite(ad7, bitRead(address, 7));
    digitalWrite(as, LOW);
    digitalWrite(rw, LOW);
    //set byte to write
    digitalWrite(ad0, bitRead(value, 0));
    digitalWrite(ad1, bitRead(value, 1));
    digitalWrite(ad2, bitRead(value, 2));
    digitalWrite(ad3, bitRead(value, 3));
    digitalWrite(ad4, bitRead(value, 4));
    digitalWrite(ad5, bitRead(value, 5));
    digitalWrite(ad6, bitRead(value, 6));
    digitalWrite(ad7, bitRead(value, 7));
    digitalWrite(rw, HIGH);
}

/** adjust a register value by 1*/
boolean adjust(byte address) {
    //read current value
    byte value = 0;
    byte b;
    if ((address &lt; 0) || (address &gt; 10)) return false;
    if (!bitRead(readbyte(regA), 7)) value = readbyte(address);
    b = readbyte(regB);
    //set SET bit of register B that will prevent double buffer update from internal buffer
    b = b | 0x80;
    writebyte(regB, b);

    if (bitRead(readbyte(regB), 7)) {
        switch (address) {
            case ADDR_CUR_SEC://seconds
                writebyte(address, 0); //reset
                break;
            case ADDR_ALM_SEC://seconds alarm
                writebyte(address, 0); //reset
                break;
            case ADDR_CUR_MIN://minutes
                if (value &gt;= 59) {
                    writebyte(address, 0);
                } else {
                    value++;
                    writebyte(address, value);
                }
                break;
            case ADDR_ALM_MIN://minutes alarm
                if (value &gt;= 59) {
                    writebyte(address, 0);
                } else {
                    value++;
                    writebyte(address, value);
                }
                break;
            case ADDR_CUR_HOUR://hours
                if (value &gt;= 23) {
                    writebyte(address, 0);
                } else {
                    value++;
                    writebyte(address, value);
                }
                break;
            case ADDR_ALM_HOUR://hours alarm
                if (value &gt;= 23) {
                    writebyte(address, 0);
                } else {
                    value++;
                    writebyte(address, value);
                }
                break;
            case ADDR_CUR_DOW://day of week
                if (value &gt;= 7) {
                    writebyte(address, 1);
                } else {
                    value++;
                    writebyte(address, value);
                }
                break;
            case ADDR_CUR_DAY:
                if (value &gt;= 31) {
                    writebyte(address, 1);
                } else {
                    value++;
                    writebyte(address, value);
                }
                break;
            case ADDR_CUR_MON://month
                if (value &gt;= 12) {
                    writebyte(address, 1);
                } else {
                    value++;
                    writebyte(address, value);
                }
                break;
            case ADDR_CUR_YEAR://year
                if (value == 99) {
                    writebyte(address, 0);
                } else {
                    value++;
                    writebyte(address, value);
                }
                break;
        }
    }

    //mask regA and clear SET bit
    b = b &amp; 0x7F;
    writebyte(regB, b);
    return true;
}

/** interrupt handler routine */
void intr() {
    interruptConter++;

    if (stopWatchStarted) {
        stopWatchCounter++;
    }

    switch (btnMode1) {
        case DM_TIME:
            switch (btnMode2) {
                case DM_ADJ_NONE:
                    dispCurrentTime();
                    break;
                case DM_ADJ_HOUR:
                    dispCurrentTime();
                    break;
                case DM_ADJ_MIN:
                    dispCurrentTime();
                    break;
                case DM_ADJ_MONTH:
                    dispCurrentDate();
                    break;
                case DM_ADJ_DAY:
                    dispCurrentDate();
                    break;
                case DM_ADJ_YEAR:
                    dispCurrentYear();
                    break;
                case DM_ADJ_DOW:
                    dispDayOfWeek();
                    break;
            }
            break;
        case DM_DATE:
            dispCurrentDate();
            break;
        case DM_YEAR:
            dispCurrentYear();
            break;
        case DM_DOW:
            dispDayOfWeek();
            break;
        case DM_STOP_WATCH:
            dispStopWatch();
            break;
        default:
            break;
    }

    //flashes the second indicator (the dot) every half second
    if (interruptConter &gt; 63) {
        interruptConter = 0;
        secondIndLEDOn = !secondIndLEDOn;
    }
}

/*********************
 * Arduino routines
 *********************/
void setup() {
    init7seg();
    pinMode(btnPin1, INPUT);
    pinMode(btnPin2, INPUT);
    digitalWrite(btnPin1, HIGH);
    digitalWrite(btnPin2, HIGH);

    pinMode(as, OUTPUT);
    pinMode(ds, OUTPUT);
    pinMode(rw, OUTPUT);

    //delay after power up to start-up
    digitalWrite(as, LOW);
    digitalWrite(ds, LOW);
    digitalWrite(rw, LOW);
    delayMicroseconds(200);

    // RS3 RS2 RS1 RS0 = 1001 set SQW output frequency to 128 Hz
    byte a = 41;
    writebyte(regA, a);

    byte b = readbyte(regB);
    b = b | 0xF;
    writebyte(regB, b);

    attachInterrupt(0, intr, RISING);
    c1 = ' ';
    c2 = ' ';
    c3 = ' ';
    c4 = ' ';
}

void loop() {
    if (digitalRead(btnPin1) == LOW &amp;&amp; !btn1Pressed) {//debouncing btn1
        delayMilliseconds(20);
        if (digitalRead(btnPin1) == LOW) {
            switch (btnMode2) {
                case DM_ADJ_NONE:
                    btnMode1 = (btnMode1 + 1) % 5;
                    break;
                case DM_ADJ_HOUR:
                    adjust(ADDR_CUR_HOUR);
                    break;
                case DM_ADJ_MIN:
                    adjust(ADDR_CUR_MIN);
                    break;
                case DM_ADJ_MONTH:
                    adjust(ADDR_CUR_MON);
                    break;
                case DM_ADJ_DAY:
                    adjust(ADDR_CUR_DAY);
                    break;
                case DM_ADJ_YEAR:
                    adjust(ADDR_CUR_YEAR);
                    break;
                case DM_ADJ_DOW:
                    adjust(ADDR_CUR_DOW);
                    break;
                default:
                    break;
            }

            btn1Pressed = true;
        }
    }

    if (digitalRead(btnPin1) == HIGH) {
        delayMilliseconds(20);

        if (digitalRead(btnPin1) == HIGH) {
            btn1Pressed = false;
        }
    }

    if (digitalRead(btnPin2) == LOW &amp;&amp; !btn2Pressed) {
        delayMilliseconds(20);

        if (digitalRead(btnPin2) == LOW) {//debouncing btn2
            if (btnMode1 == DM_TIME) {
                btnMode2 = (btnMode2 + 1) % 7;
            }

            if (btnMode1 == DM_STOP_WATCH &amp;&amp; !stopWatchStarted &amp;&amp; stopWatchInit) {
                stopWatchInit = false;
                stopWatchStarted = true;
            } else if (btnMode1 == DM_STOP_WATCH &amp;&amp; stopWatchStarted &amp;&amp; !stopWatchInit) {
                stopWatchStarted = false;
            } else if (btnMode1 == DM_STOP_WATCH &amp;&amp; !stopWatchStarted &amp;&amp; !stopWatchInit) {
                stopWatchInit = true;
                stopWatchCounter = 0;
            }

            btn2Pressed = true;
        }
    }

    if (digitalRead(btnPin2) == HIGH) {//debouncing btn2
        delayMilliseconds(20);
        if (digitalRead(btnPin2) == HIGH) {
            btn2Pressed = false;
        }
    }
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2010/06/05/a-clock-stop-watch-based-on-bq3287/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Google PAC-MAN</title>
		<link>http://www.kerrywong.com/2010/05/21/google-pac-man/</link>
		<comments>http://www.kerrywong.com/2010/05/21/google-pac-man/#comments</comments>
		<pubDate>Fri, 21 May 2010 15:35:17 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Miscellaneous]]></category>
		<category><![CDATA[Google]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=2146</guid>
		<description><![CDATA[The Google PAC-MAN logo is actually a live game! I really admire Google&#8217;s creativity and it is actually quite impressive to cramp such a game into just 58K of javascript (http://www.google.com/logos/js/pacman10-hp.2.js) and a small PNG file:]]></description>
			<content:encoded><![CDATA[<p>The Google PAC-MAN logo is actually a live game! <span id="more-2146"></span><br />
<div id="attachment_2147" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/05/google_pacman.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/05/google_pacman-300x222.jpg" alt="Google PAC-MAN" title="Google PAC-MAN" width="300" height="222" class="size-medium wp-image-2147" /></a><p class="wp-caption-text">Google PAC-MAN</p></div></p>
<p>I really admire Google&#8217;s creativity and it is actually quite impressive to cramp such a game into just 58K of javascript (<a href="http://www.google.com/logos/js/pacman10-hp.2.js">http://www.google.com/logos/js/pacman10-hp.2.js</a>) and a small PNG file:</p>
<div id="attachment_2149" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/05/google_pacman_png.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/05/google_pacman_png-300x158.jpg" alt="Google PAC-MAN (behind the scene)" title="Google PAC-MAN (behind the scene)" width="300" height="158" class="size-medium wp-image-2149" /></a><p class="wp-caption-text">Google PAC-MAN (behind the scene)</p></div>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2010/05/21/google-pac-man/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Arduino Development Using NetBeans</title>
		<link>http://www.kerrywong.com/2010/05/16/arduino-development-using-netbeans/</link>
		<comments>http://www.kerrywong.com/2010/05/16/arduino-development-using-netbeans/#comments</comments>
		<pubDate>Sun, 16 May 2010 18:21:55 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[AVR/Arduino]]></category>
		<category><![CDATA[Arduino]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[NetBeans]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=2030</guid>
		<description><![CDATA[The Arduino development environment is probably the preferred development platform for the majority of Arduino users. It is lean and relatively easy to use. Quite a few examples are at your finger tip and even for people without much programming experience, it is relatively easy to get started. You can write and upload your sketches [...]]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://arduino.cc/en/Main/Software">Arduino development environment</a> is probably the preferred development platform for the majority of Arduino users. It is lean and relatively easy to use. Quite a few examples are at your finger tip and even for people without much programming experience, it is relatively easy to get started. You can write and upload your sketches (programs) without the need to ever leave the IDE.<span id="more-2030"></span></p>
<p>Despite its convenience, the Arduino IDE lacks some key features most modern IDEs have. To name a few, the Arduino IDE does not yet support <a href="http://en.wikipedia.org/wiki/Autocomplete">auto-completion</a>, <a href="http://en.wikipedia.org/wiki/Code_folding">code folding</a> and <a href="http://en.wikipedia.org/wiki/Context-sensitive_help">contextual help</a>. And the integrated parser sometimes have difficulties parsing complex code structures and do not give adequate information for the errors encountered. While it does not matter much for writing simple programs, the drawbacks are obvious when developing more complex applications. Since I am a software developer, I personally prefer a more advanced IDE.</p>
<p>If you are using <a href=" http://www.eclipse.org/">Eclipse</a>, then there is already a <a href="http://www.arduino.cc/playground/Code/Eclipse">plugin available</a> for AVR development, though I have not personally tried it I have seen other people using it regularly. Looking at the <a href="http://www.arduino.cc/playground/Code/Eclipse">Arduino playground instructions for this plugin</a>, it seems that it is pretty straight forward to set up. But if you are using <a href="http://www.netbeans.org">NetBeans</a>, currently there&#8217;s no Arduino support yet.</p>
<p>Luckily, it is actually fairly straight forward to add Arduino support in the NetBeans environment. In this article, I will show you step by step instructions on how to prepare your NetBeans environment for Arduino development purpose.</p>
<p>For those who are impatient and know your way around the NetBeans environment, you can download and install <a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/05/ArduinoPlugin_v1.0.tar.gz">ArduinoPlugin_v1.0.tar.gz</a> (Tools -> Plug-ins, under Downloaded tab, choose add plug-ins) and get started right away. You do need to configure your NetBeans environment to support avr-gcc tool chain before you can start using the Arduino module. If you are unsure how to do this, please read on.</p>
<h3>Prerequisite</h3>
<p>This plugin requires a functional Arduino development environment. Since this plug-in relies on the Arduino core libraries for code compilation, Arduino must be installed first. You can refer to the <a href="http://arduino.cc/en/Guide/HomePage">Getting Started with Arduino</a> guide on the official Arduino site on how to install the Arduino programming environment.</p>
<p>The instructions in this article assumes that you are running Arduino under Linux, but I think you can adapt it to Windows environment with relatively few changes. Here is a list of the software versions I have installed on my PC.</p>
<blockquote><p>
Ubuntu 10.04 (64bit)<br />
avr-gcc 4.3.4<br />
avrdude 5.10<br />
RXTX-2.2pre2<br />
NetBeans 6.8<br />
arduino-0018
</p></blockquote>
<p>Depending on your particular settings (e.g. the installation path of arduino-0018 is not located under your home directory or it is installed under a different directory name), minor modifications to the template might be needed.</p>
<h3>Configure AVR Tool Chain</h3>
<p>To setup the NetBeans environment, we need to first setup the AVR tool chain. To do so, first launch NetBeans, navigate to Tools -> Options and click &#8220;Add&#8221; under C/C++/Build Tools (see screen shot below), and from there we can create a new tool chain called Arduino and configure the paths in the right-hand-side pane accordingly. Here is a screenshot of the tool chain configuration on my system:</p>
<blockquote><p>
Base Directory: /usr/bin<br />
C Compiler: /usr/bin/avr-gcc<br />
C++ Compiler: /usr/bin/avr-g++<br />
Assembler: /usr/bin/avr-as<br />
Debugger: /usr/bin/gdb (this is not important since we do not run Arduino applications within NetBeans anyway)
</p></blockquote>
<div id="attachment_2042" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/05/avrgcctoolchain.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/05/avrgcctoolchain-300x253.png" alt="avr-gcc tool chain setup in NetBeans" title="avr-gcc tool chain setup in NetBeans" width="300" height="253" class="size-medium wp-image-2042" /></a><p class="wp-caption-text">avr-gcc tool chain setup in NetBeans</p></div>
<p>In order for the auto-complete feature to work with the Arduino/AVR header files, we also need to setup the paths under the Code Assistance tab. To begin with, you would need to setup the following paths:</p>
<blockquote><p>
~/arduino-0018/hardware/arduino/cores/arduino (assuming that you installed Arduino 0018 under your home directory)<br />
~/arduion-0018/libraries/<br />
/usr/lib/gcc/avr/4.3.4/include
</p></blockquote>
<p>If you use libraries located in other locations, you will need to add those paths to the C/C++ compiler code assistance tab as well.</p>
<h3>Install the Arduino Plugin</h3>
<p>To install the plugin, download the NetBeans module first (<a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/05/ArduinoPlugin_v1.0.tar.gz">ArduinoPlugin_v1.0.tar.gz</a>). Use the following command to extract the NetBeans Module (ArduinoPlugin_v1.0.nbm):</p>
<blockquote><p>
tar zxf ArduinoPlugin_v1.0.tar.gz
</p></blockquote>
<p>Then go to Tools -> Plugins, under Downloaded tab, choose Add plugins. Navigate to where you saved the .nbm file and click OK. </p>
<p>After installing the plugin, the plugin option screen should look like the following:</p>
<div id="attachment_2107" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/05/netbeansplugin.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/05/netbeansplugin-300x245.png" alt="Arduino Plugin installed" title="Arduino Plugin installed" width="300" height="245" class="size-medium wp-image-2107" /></a><p class="wp-caption-text">Arduino Plugin installed</p></div>
<h3>How to use</h3>
<p>To create an Arduino project, go to project new and choose Arduino project template.<br />
<div id="attachment_2114" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/05/newproject.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/05/newproject-300x203.png" alt="Create an Arduino Project" title="Create an Arduino Project" width="300" height="203" class="size-medium wp-image-2114" /></a><p class="wp-caption-text">Create an Arduino Project</p></div></p>
<p>After the project is created, you should see two files (main.pde and makefile) under Source Files folder, and main.pde contains the code skeleton:</p>
<pre class="brush: cpp;">
#define __AVR_ATmega328P__

#include &lt;binary.h&gt;
#include &lt;HardwareSerial.h&gt;
#include &lt;pins_arduino.h&gt;
#include &lt;WConstants.h&gt;
#include &lt;wiring.h&gt;
#include &lt;wiring_private.h&gt;
#include &lt;WProgram.h&gt;
#include &lt;EEPROM/EEPROM.h&gt;

void setup()
{

}

void loop()
{

}
</pre>
<p>I tried to make the code structure look as close to that in Arduino IDE as possible, but for the code auto completion to work, some extra includes are needed. Also, note that I have included the MCU definition (#define __AVR_ATmega328P__) to get the the MCU specific intellisense work. You can change this to the type of MCU you are targeting.</p>
<div id="attachment_2120" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/05/codecompletion.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/05/codecompletion-300x140.png" alt="Auto Completion" title="Auto Completion" width="300" height="140" class="size-medium wp-image-2120" /></a><p class="wp-caption-text">Auto Completion</p></div>
<p>To build your project, right click on the makefile and choose make or make clean. If your build is successful, you should see a HEX file built in the applet directory within your project root. And you can use the Make Target -> upload option to upload the HEX file onto the Arduino board.</p>
<div id="attachment_2118" class="wp-caption aligncenter" style="width: 299px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/05/maketarget.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/05/maketarget-289x300.png" alt="Build and Upload" title="Build and Upload" width="289" height="300" class="size-medium wp-image-2118" /></a><p class="wp-caption-text">Build and Upload</p></div>
<h3>Behind the scene</h3>
<p>The Arduino plugin for NetBeans is developed as a <a href="http://platform.netbeans.org/tutorials/nbm-projectsamples.html">NetBeans project sample module</a>. The makefile is adapted from the make file used within the Arduino environment and is discussed <a href="http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1265576847">here</a>.</p>
<p>I had put some additional comments in places where you might need to edit for it to work with your projects. For instance, your project may link to more modules than the ones listed below.</p>
<blockquote><p>
#Note that if your program has dependencies other than those<br />
#already listed below, you will need to add them accordingly.<br />
C_MODULES =  \<br />
$(ARDUINO)/wiring_pulse.c \<br />
$(ARDUINO)/wiring_analog.c \<br />
$(ARDUINO)/pins_arduino.c \<br />
$(ARDUINO)/wiring.c \<br />
$(ARDUINO)/wiring_digital.c \<br />
$(ARDUINO)/WInterrupts.c \<br />
$(ARDUINO)/wiring_shift.c \</p>
<p>CXX_MODULES = \<br />
$(ARDUINO)/Tone.cpp \<br />
$(ARDUINO)/main.cpp \<br />
$(ARDUINO)/WMath.cpp \<br />
$(ARDUINO)/Print.cpp \<br />
$(ARDUINO)/HardwareSerial.cpp \<br />
$(ARDUINO_LIB)/EEPROM/EEPROM.cpp \
</p></blockquote>
<p>Also, I followed the technique used in the Arduino IDE to assemble the sketch with other necessary information and the main program at compile time (see the portion of the makefile below) to keep main.pde as simple as possible. The only issue is that compilation errors are referenced against the assembled source code rather than the code you write in main.pde. I had originally thought about putting all the necessary code in main.pde and thus would not require code merge at compile time, but it would make the code less compatible with the Arduino IDE environment.</p>
<blockquote><p>
#applet_files: main.pde<br />
applet/$(TARGET).cpp: main.pde<br />
	# Here is the &#8220;preprocessing&#8221;.<br />
	# It creates a .cpp file based with the same name as the .pde file.<br />
	# On top of the new .cpp file comes the WProgram.h header.<br />
	# and prototypes for setup() and Loop()<br />
	# Then the .cpp file will be compiled. Errors during compile will<br />
	# refer to this new, automatically generated, file.<br />
	# Not the original .pde file you actually edit&#8230;<br />
	test -d applet || mkdir applet<br />
	echo &#8216;#include &#8220;WProgram.h&#8221;&#8216; > applet/$(TARGET).cpp<br />
	echo &#8216;void setup();&#8217; >> applet/$(TARGET).cpp<br />
	echo &#8216;void loop();&#8217; >> applet/$(TARGET).cpp<br />
	cat main.pde >> applet/$(TARGET).cpp
</p></blockquote>
<h3>Future Enhancement</h3>
<p>Currently, there is no serial port monitor integrated with the NetBeans environment. So if your code uses the Serial class (i.e. Serial.println()), you will have to use the serial monitor bundled with Arduino. This should not be a big issue though, since even in Arduino, you have to click on the Serial Monitor every time after you upload the code to use it any way. I am planning on integrating the serial monitor with NetBeans in the future but it would probably take some time.</p>
<h4>Download</h4>
<p>Arduino plugin for NetBeans: <a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/05/ArduinoPlugin_v1.0.tar.gz">ArduinoPlugin_v1.0.tar.gz</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2010/05/16/arduino-development-using-netbeans/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Working With LM19 Temperature Sensor</title>
		<link>http://www.kerrywong.com/2010/05/09/working-with-lm19-temperature-sensor/</link>
		<comments>http://www.kerrywong.com/2010/05/09/working-with-lm19-temperature-sensor/#comments</comments>
		<pubDate>Mon, 10 May 2010 00:13:27 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[AVR/Arduino]]></category>
		<category><![CDATA[Arduino]]></category>
		<category><![CDATA[Atmega328P]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[LM19]]></category>
		<category><![CDATA[Temperature Sensor]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=2047</guid>
		<description><![CDATA[LM19 is an analog temperature sensor that operates over a while temperature range (-55 to 130 Celsius). It is very easy to interface it with a microcontroller due to is fairly linear voltage output. The following code listing illustrates how to obtain temperature readings from LM19 with an Arduino. The code assumed that the sensor [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.national.com/ds/LM/LM19.pdf">LM19</a> is an analog temperature sensor that operates over a while temperature range (-55 to 130 Celsius). It is very easy to interface it with a microcontroller due to is fairly linear voltage output.<span id="more-2047"></span></p>
<p>The following code listing illustrates how to obtain temperature readings from LM19 with an <a href="http://www.arduino.cc">Arduino</a>. The code assumed that the sensor output is connected to Analog 0 pin.</p>
<pre class="brush: cpp;">
void setup()
{
    Serial.begin(9600);
}

void loop()
{
  float vin = 5.0 * analogRead(0) / 1024.0;
  Serial.print(vin);
  Serial.print(&quot;  &quot;);
  float tempC = (1.8663 - vin) / 0.01169;
  float tempF = 1.8 * tempC + 32.0;
  Serial.print(tempC);
  Serial.print(&quot;  &quot;);
  Serial.println(tempF);
  delay(100);
}
</pre>
<p>In the code above, I used the approximated linear transfer function shown below. It is fairly accurate when the temperature range is around room temperature.<br />
\[T_{Celcius} = \frac{(1.8663-V_o}{0.01169}\]</p>
<p>For more accurate temperature measurement over the full operating range, the following equation can be used:<br />
\[T_{Celcius} = \sqrt{2.1962 \times 10^6 + \frac {1.8639 - V_o}{3.88 \times 10^{-6}}} - 1481.96\]</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2010/05/09/working-with-lm19-temperature-sensor/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Library for LTC1665/LTC1660</title>
		<link>http://www.kerrywong.com/2010/05/02/a-library-for-ltc1665ltc1660/</link>
		<comments>http://www.kerrywong.com/2010/05/02/a-library-for-ltc1665ltc1660/#comments</comments>
		<pubDate>Mon, 03 May 2010 00:21:44 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[AVR/Arduino]]></category>
		<category><![CDATA[AD/DA]]></category>
		<category><![CDATA[Arduino]]></category>
		<category><![CDATA[Atmega328P]]></category>
		<category><![CDATA[AVR]]></category>
		<category><![CDATA[C++]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=2005</guid>
		<description><![CDATA[ATmega328p does not provide any Digital/Analog conversion channels (although the D/A conversion can be simulated by means of measuring the PWM output). We can easily add up to eight D/A channels using either a LTC1665 (8 bit) or LTC1660 (10 bit) from Linear Technology. What makes LTC1665/LTC1660 attractive is that the D/A converters addressable via [...]]]></description>
			<content:encoded><![CDATA[<p>ATmega328p does not provide any Digital/Analog conversion channels (although the D/A conversion can be simulated by means of measuring the PWM output). We can easily add up to eight D/A channels using either a <a href="http://cds.linear.com/docs/Datasheet/166560f.pdf">LTC1665 (8 bit) or LTC1660 (10 bit)</a> from <a href="http://www.linear.com/">Linear Technology</a>.<span id="more-2005"></span></p>
<p>What makes LTC1665/LTC1660 attractive is that the D/A converters addressable via the serial interface. And thus, controlling the eight D/A channels requires relatively few connections with ATmega328p.</p>
<p>The schematic below illustrates how to utilize a D/A channel with input from ATmega328p. Pin  IN, SCK, CSLD, CLR can be connected to any pins that accept digital input. And the pin labeled Analog Out outputs the conversion result.</p>
<div id="attachment_2008" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/05/LTC1665CN.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/05/LTC1665CN-300x261.png" alt="LTC1665CN" title="LTC1665CN" width="300" height="261" class="size-medium wp-image-2008" /></a><p class="wp-caption-text">LTC1665CN</p></div>
<p>The output voltage from the function output() is determined by:<br />
\[Vout = \frac{Vref \times val}{256}\]<br />
for LTC1665 (8 bit), and<br />
\[Vout = \frac{Vref \times val}{1024}\]<br />
for LTC1660 (10 bit). In my example above, Vref is connected to Vcc and is typically around 5V.</p>
<p>The following code uses Arduino to drive the DAC clock. To test the conversion result, the analog output is connected with an Arduino analog input pin.</p>
<pre class="brush: cpp;">
const int pinIN = 8;
const int pinSCK = 7;
const int pinCSLD= 3;
const int pinCLR =12;

const int pinAnalogOut = 5;

void setup()
{
  pinInit();
  Serial.begin(9600);
  output(1, 64);
  Serial.println(analogRead(pinAnalogOut));
}

void pinInit()
{
  pinMode(pinIN, OUTPUT);
  pinMode(pinSCK, OUTPUT);
  pinMode(pinCSLD, OUTPUT);
  pinMode(pinCLR, OUTPUT);

  digitalWrite(pinCLR, HIGH);
  digitalWrite(pinSCK, LOW);
  digitalWrite(pinCSLD, HIGH);
}

//Performs D/A conversion
void output(long chn, long val)
{
  //the control word is 16 bits
  //the high 4 bits defines the output channel
  long t = chn &lt;&lt; 12;

  //the lower 4 bits are don't cares so we make
  //them zeros.
  t = t | val &lt;&lt; 4;
  //for LTC1660 it has 10bit resolution this line will
  //need to change to:
  //t = t | val &lt;&lt; 2;

  digitalWrite(pinCSLD, LOW);
  for (long i = 15; i &gt;= 0; i--)
  {
    long b = (t &gt;&gt; i) &amp; 1;
    digitalWrite(pinIN, b);
    digitalWrite(pinSCK, HIGH);
    digitalWrite(pinSCK, LOW);
  }

  digitalWrite(pinCSLD, HIGH);
}

void loop()
{
}
</pre>
<p>The bit resolution difference between LTC1665 and LTC1660 is handled by the code within the output() function.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2010/05/02/a-library-for-ltc1665ltc1660/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>An Arduino ICSP Board</title>
		<link>http://www.kerrywong.com/2010/04/24/an-arduino-icsp-board/</link>
		<comments>http://www.kerrywong.com/2010/04/24/an-arduino-icsp-board/#comments</comments>
		<pubDate>Sun, 25 Apr 2010 02:08:05 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[AVR/Arduino]]></category>
		<category><![CDATA[Arduino]]></category>
		<category><![CDATA[Atmega328P]]></category>
		<category><![CDATA[Bootloader]]></category>
		<category><![CDATA[ICSP]]></category>
		<category><![CDATA[ISP]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=1938</guid>
		<description><![CDATA[I have been using the bit-banging method to boot-load ATmega328p with Arduino bootloader for a while, and Kimo&#8217;s method worked quite well for me. If you need to flash a lot of chips however, you might not want to swap out the chip on your Arduino board every single time you need to flash another [...]]]></description>
			<content:encoded><![CDATA[<p>I have been using the <a href="http://en.wikipedia.org/wiki/Bit-banging">bit-banging</a> method to <a href="http://www.kerrywong.com/2010/04/02/on-atmega328-bootloading-with-ftdi-bitbang-method/">boot-load ATmega328p</a> with Arduino bootloader for a while, and <a href="http://www.geocities.jp/arduino_diecimila/bootloader/index_en.html">Kimo&#8217;s method</a> worked quite well for me. If you need to flash a lot of chips however, you might not want to swap out the chip on your Arduino board every single time you need to flash another chip as you do not want to accidentally damage the socket (or the board) in the process. After all, the DIP socket is not designed for this kind of repetitive use. <span id="more-1938"></span></p>
<p>So, I decided to make a separate <a href="http://en.wikipedia.org/wiki/In-system_programming">ICSP</a> board just for programming ATmega328p. The concept is quite simple, as you can see in the schematics below it basically is a bare bone ATmega328 board with a reset button and ICSP headers. I added an LED to pin 19 (Arduino pin 13) so that if the boot loader is flashed successfully, the LED will blink just as would on an Arduino board. The LED will also serve as an indicator during flashing.</p>
<div id="attachment_1945" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/04/atmega328pISPboard.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/04/atmega328pISPboard-300x289.png" alt="ATmega328p ICSP Board" title="ATmega328p ICSP Board" width="300" height="289" class="size-medium wp-image-1945" /></a><p class="wp-caption-text">ATmega328p ICSP Board</p></div>
<p>The following is the board with the ICSP header based on the schematics shown above. This board is not just limited to burning Arduino boot loader or other Arduino programs though, it can serve as a standard template for any ATmega328 based system you build. Ideally, you probably want to replace the standard DIP socket with a ZIF socket so that it is more suitable to be used as a programmer board. </p>
<div id="attachment_1952" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/04/atmega328ISPboard_11.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/04/atmega328ISPboard_11-300x225.jpg" alt="ATmega328 ICSP Board" title="ATmega328 ICSP Board" width="300" height="225" class="size-medium wp-image-1952" /></a><p class="wp-caption-text">ATmega328 ICSP Board</p></div>
<p>Here is a picture taken while I was testing flashing boot loader with the bit-banging method. Since I kept the ICSP header pin layout the same as on the Arduino board, I can use the same cable as <a href="http://www.kerrywong.com/2010/04/02/on-atmega328-bootloading-with-ftdi-bitbang-method/">I used before</a>. You can find  more details on how to make the cable and <a href="http://www.geocities.jp/arduino_diecimila/bootloader/index_en.html">here</a>. </p>
<div id="attachment_1955" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/04/atmega328ISPboard_3.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/04/atmega328ISPboard_3-300x225.jpg" alt="Testing the ICSP board" title="Testing the ICSP board" width="300" height="225" class="size-medium wp-image-1955" /></a><p class="wp-caption-text">Testing the ICSP board</p></div>
<p>I decided to add voltage regulation circuitry so that I can use different power sources. The finished ICSP board with case is shown below:</p>
<div id="attachment_1948" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/04/atmega328ISPboard_1.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/04/atmega328ISPboard_1-300x225.jpg" alt="Finished ATmega328 ICSP Board" title="Finished ATmega328 ICSP Board" width="300" height="225" class="size-medium wp-image-1948" /></a><p class="wp-caption-text">Finished ATmega328 ICSP Board</p></div>
<p>Here&#8217;s another picture of the ICSP board in action:</p>
<div id="attachment_1966" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/04/atmega328ISPboard_4.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/04/atmega328ISPboard_4-300x225.jpg" alt="Finished ATmega328 ICSP Board" title="Finished ATmega328 ICSP Board" width="300" height="225" class="size-medium wp-image-1966" /></a><p class="wp-caption-text">Finished ATmega328 ICSP Board</p></div>
<p>And of course, you can also use a regular programmer to program chips on this ICSP board as well.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2010/04/24/an-arduino-icsp-board/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Interfacing LIS3LV02DL Using SPI &#8212; II</title>
		<link>http://www.kerrywong.com/2010/04/17/interfacing-lis3lv02dl-using-spi-ii/</link>
		<comments>http://www.kerrywong.com/2010/04/17/interfacing-lis3lv02dl-using-spi-ii/#comments</comments>
		<pubDate>Sun, 18 Apr 2010 01:02:34 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[AVR/Arduino]]></category>
		<category><![CDATA[Accelerometer]]></category>
		<category><![CDATA[Atmega328P]]></category>
		<category><![CDATA[AVR]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Physical Computing]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=1842</guid>
		<description><![CDATA[In my last post, I described in detail how to hand solder LIS3LV02DL, an LGA packaged accelerometer chip. And here I will show you how the communication with Arduino is done using SPI. Before I start, I should mention that according to the product documentation, the normal operation voltage (Vdd) for LIS3LV02DL is between 2.16V [...]]]></description>
			<content:encoded><![CDATA[<p>In my <a href="http://www.kerrywong.com/2010/04/16/interfacing-lis3lv02dl-using-spi-i/">last post</a>, I described in detail how to hand solder <a href="http://www.st.com/stonline/books/pdf/docs/12094.pdf">LIS3LV02DL</a>, an LGA packaged accelerometer chip. And here I will show you how the communication with Arduino is done using <a href="http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus">SPI</a>.<span id="more-1842"></span></p>
<p>Before I start, I should mention that according to the product documentation, the normal operation voltage (Vdd) for LIS3LV02DL is between 2.16V and 3.6V. Ideally you should interface LIS3LV02DL with  CMOS logic level rather than the standard TTL logic level Arduino provides. In order for the accelerometer to operate within spec, you should lower the Arduino supply voltage to 3.3V and will most likely have to reduce the crystal frequency to 8-12MHz to accommodate the reduced voltage. </p>
<p>That said, the absolute maximum supply voltage (Vdd) for LIS3LV02DL is 6V. So it should be able to withstand the 5V Arduino operates on. I was able to power LIS3LV02DL using Arduino&#8217;s power source without experiencing any issues. But, it is definitely not recommended for prolonged use since according to the product documentation: </p>
<blockquote><p><em>&#8220;exposure to maximum rating conditions for extended periods may affect device reliability.&#8221;</em></p></blockquote>
<p>I used the method I mentioned <a href="http://www.kerrywong.com/2010/04/16/interfacing-lis3lv02dl-using-spi-i/">previously</a> to mount the chip onto a perf board and soldered on connector pins to make it easier for testing on a breadboard.</p>
<p>My setup is like this:</p>
<div id="attachment_1919" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/04/accelerometer_5.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/04/accelerometer_5-300x225.jpg" alt="LIS3LV02DL Accelerometer With Arduino" title="LIS3LV02DL Accelerometer With Arduino" width="300" height="225" class="size-medium wp-image-1919" /></a><p class="wp-caption-text">LIS3LV02DL Accelerometer with Arduino</p></div>
<p>With LIS3LV02DL pin 3 connected to Arduino digital pin 11, LIS3LV02DL pin 2 connected to Arduino digital pin 12, pin 5 connected to digital pin 13 and pin 6 connected to digital pin 10.</p>
<p>The following is the code to retrieve data from the accelerometer using SPI.</p>
<pre class="brush: cpp;">

#define DATAOUT 11//MOSI lis3lv02dl pin3
#define DATAIN  12//MISO lis3lv02dl pin2
#define SPICLOCK  13//sck lis3lv02dl pin5
#define CS 10//ss lis3lv02dl pin6, active low

//register addresses
const int REG_WHO_AM_I = 0x0f; //3A
const int REG_OFFSET_X = 0x16;
const int REG_OFFSET_Y = 0x17;
const int REG_OFFSET_Z = 0x18;
const int REG_GAIN_X = 0x19;
const int REG_GAIN_Y = 0x1A;
const int REG_GAIN_Z = 0x1B;
const int REG_CTRL_REG1 = 0x20;
const int REG_CTRL_REG2 = 0x21;
const int REG_CTRL_REG3 = 0x22;
const int REG_HP_FILTER_RESET = 0x23;
const int REG_STATUS_REG = 0x27;
const int REG_OUTX_L = 0x28;
const int REG_OUTX_H = 0x29;
const int REG_OUTY_L = 0x2a;
const int REG_OUTY_H = 0x2b;
const int REG_OUTZ_L = 0x2c;
const int REG_OUTZ_H = 0x2d;
const int REG_FF_WU_CFG = 0x30;
const int REG_FF_WU_SRC = 0x31;
const int REG_FF_WU_ACK = 0x32;
const int REG_FF_WU_THS_L = 0x34;
const int REG_FF_WU_THS_H = 0x35;
const int REG_FF_WU_DURATION = 0x36;
const int REG_DD_CFG = 0x38;
const int REG_DD_SRC = 0x39;
const int REG_DD_ACK = 0x3a;
const int REG_DD_THSI_L = 0x3c;
const int REG_DD_THSI_H = 0x3d;
const int REG_DD_THSE_L = 0x3e;
const int REG_DD_THSE_H = 0x3f;

//axis definitions
const int AXIS_X = 1;
const int AXIS_Y = 2;
const int AXIS_Z = 3;

const int CTRL_REG2_FS = 7;

void setup()
{
  byte b = 0;

  Serial.begin(9600);

  pinSetup();
  initSys();
  b = readRegister(REG_WHO_AM_I);
  Serial.println(b, HEX); //should be 3A

  setScale(1); //set range to 6g
}

void loop()
{
  Serial.print(&quot; x = &quot;);
  Serial.print(getValue(AXIS_X));
  Serial.print(&quot; y = &quot;);
  Serial.print(getValue(AXIS_Y));
  Serial.print(&quot; z = &quot;);
  Serial.println(getValue(AXIS_Z));
}

//transfer a byte using SPI
byte spiTransfer(volatile byte data)
{
  SPDR = data;

  while (!(SPSR &amp; _BV(SPIF)));

  return SPDR;
}

void initSys()
{
  //disable device
  digitalWrite(CS,HIGH); 

  //initialize SPI
  SPCR = _BV(SPE) | _BV(MSTR)| _BV(CPOL)| _BV(CPHA);    

  //enable all axes
  writeRegister(REG_CTRL_REG1, 0x87);
}

void pinSetup()
{
  pinMode(DATAOUT, OUTPUT);
  pinMode(DATAIN, INPUT);
  pinMode(SPICLOCK,OUTPUT);
  pinMode(CS,OUTPUT);
}

byte getGain(int axis)
{
  byte r = 0;

  switch (axis)
  {
    case AXIS_X:
      r = readRegister(REG_GAIN_X);
    break;
    case AXIS_Y:
      r = readRegister(REG_GAIN_Y);
    break;
    case AXIS_Z:
      r = readRegister(REG_GAIN_Z);
    break;
    default:
      r = 0xff;
    break;
  }

  return r;
}

byte getOffset(int axis)
{
  byte r = 0;

  switch (axis)
  {
    case AXIS_X:
      r = readRegister(REG_OFFSET_X);
    break;
    case AXIS_Y:
      r = readRegister(REG_OFFSET_Y);
    break;
    case AXIS_Z:
      r = readRegister(REG_OFFSET_Z);
    break;
    default:
      r = 0xff;
    break;
  }

  return r;
}

void setScale(byte s)
{
  byte r = readRegister(REG_CTRL_REG2);

  if (s == 0) { // 2g
    r &amp;= ~_BV(CTRL_REG2_FS);
  } else { //6g
    r |= _BV(CTRL_REG2_FS);
  }

 writeRegister(REG_CTRL_REG2, r);
}

int getValue(int axis)
{
  int r = 0;
  byte h, l;

  switch (axis)
  {
    case AXIS_X:
      l = readRegister(REG_OUTX_L);
      h = readRegister(REG_OUTX_H);
    break;
    case AXIS_Y:
      l = readRegister(REG_OUTY_L);
      h = readRegister(REG_OUTY_H);
    break;
    case AXIS_Z:
      l = readRegister(REG_OUTZ_L);
      h = readRegister(REG_OUTZ_H);
    break;
    default:
      l = 0;
      h = 0;
    break;
  }

  r = h &lt;&lt; 8 | l;

  return r;
}

byte readRegister(byte reg)
{
   digitalWrite(CS, LOW);
   spiTransfer(reg | 0x80);
   byte b = spiTransfer(0);
   digitalWrite(CS, HIGH); 

   return b;
}

void writeRegister(byte reg, byte data)
{
   digitalWrite(CS, LOW);
   spiTransfer(reg &amp; 0x7F);
   spiTransfer(data);
   digitalWrite(CS, HIGH);
}
</pre>
<p>In the global constants area, I listed all the registers available to LIS3LV02DL. It is relatively straight-forward to use them and you can consult the product documentation for more information. The readRegister/writeRegister are the two main functions to read from and write to the registers defined earlier. getValue returns the accelerometer reading of the axis specified. setScale sets the scale to either 2G or 6G, etc.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2010/04/17/interfacing-lis3lv02dl-using-spi-ii/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Interfacing LIS3LV02DL Using SPI &#8212; I</title>
		<link>http://www.kerrywong.com/2010/04/16/interfacing-lis3lv02dl-using-spi-i/</link>
		<comments>http://www.kerrywong.com/2010/04/16/interfacing-lis3lv02dl-using-spi-i/#comments</comments>
		<pubDate>Sat, 17 Apr 2010 01:03:33 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[AVR/Arduino]]></category>
		<category><![CDATA[Accelerometer]]></category>
		<category><![CDATA[Arduino]]></category>
		<category><![CDATA[Atmega328P]]></category>
		<category><![CDATA[LGA]]></category>
		<category><![CDATA[SPI]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=1837</guid>
		<description><![CDATA[LIS3LV02DL is a MEMS three-axis digital linear accelerometer that provides both I2C and SPI interfaces for communicating with microprocessors. My work here is largely based on the work done at Near Future Laboratory. Instead of using a commercially available LIS3LV02DQ break-out board (LIS3LV02DQ is QFP packaging equivalent of LIS3LV02DL), I chose to hand solder an [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.st.com/stonline/books/pdf/docs/12094.pdf">LIS3LV02DL</a> is a <a href="http://en.wikipedia.org/wiki/Microelectromechanical_systems">MEMS</a> three-axis digital linear <a href="http://en.wikipedia.org/wiki/Accelerometer">accelerometer</a> that provides both I2C and SPI interfaces for communicating with microprocessors. My work here is largely based on the work done at <a href="http://www.nearfuturelaboratory.com/2006/09/22/arduino-and-the-lis3lv02dq-triple-axis-accelerometer/">Near Future Laboratory</a>. Instead of using a commercially available LIS3LV02DQ break-out board (LIS3LV02DQ is <a href="http://en.wikipedia.org/wiki/Chip_carrier">QFP</a> packaging equivalent of LIS3LV02DL), I chose to hand solder an LIS3LV02DL (which is uses <a href="http://en.wikipedia.org/wiki/Chip_carrier">LGA</a> packaging). And I have made some changes to the code sample to support more functionality.<span id="more-1837"></span></p>
<p>Many people are afraid of using LGA components in their projects as these components tend to be difficult to work with. They might be a bit harder to work with than ICs using DIP packaging, but you can easily make an adapter for them using only a standard soldering iron (15W to 30W). And all you need is a steady hand and some patience.</p>
<p>So for the first part of this two-part series, I will share my technique of how to make the LGA adapter using a perf-board. And for my next post, I will show you the programming behind to communicate with the <a href="http://www.arduino.cc">Arduino</a>. The hand soldering method I used here is especially suitable for working with components with only a handful of pins (in this case 16 pins).</p>
<h3>1. Preperation</h3>
<p>Since the LGA chip is extremely small (see actual size below), it can be damaged easily. So special care must be taken during handling and soldering. </p>
<div id="attachment_1859" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/04/accelerometer_1.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/04/accelerometer_1-300x225.jpg" alt="The actual size of LIS3LV02DL" title="The actual size of LIS3LV02DL" width="300" height="225" class="size-medium wp-image-1859" /></a><p class="wp-caption-text">The actual size of LIS3LV02DL</p></div>
<p>To work with such a small component, you need to clean your soldering iron&#8217;s tip and re-surface the tip if necessary so that the tip is at most 1mm in diameter. The soldering iron I used is just a very basic 30W one you can buy from <a href="http://www.walmart.com">Walmart</a> or <a href="http://www.radioshack.com/">RadioShack</a>. A fancier one can probably make life easier, but it is not necessary.</p>
<h3>2. Mounting the chip </h3>
<p>Without using any special printed circuit board, the best way to deal with LGA components is to turn it upside down and glue it onto the board like this:</p>
<div id="attachment_1869" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/04/accelerometer_2.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/04/accelerometer_2-300x225.jpg" alt="LIS3LV02DL glued onto a perf board" title="LIS3LV02DL glued onto a perf board" width="300" height="225" class="size-medium wp-image-1869" /></a><p class="wp-caption-text">LIS3LV02DL glued onto a perf board</p></div>
<p>Do not use too much glue as excessive glue can get on the soldering pads and make it very difficult to solder later. Usually, a tiny drop of super glue would do the trick. Also, consult the datasheet for pin orientation. The first pin is usually marked on both sides of the chip (in this case it is the tiny dot near the upper left corner, right under the pin pad).</p>
<h3>3. Soldering </h3>
<p>This is obviously the most crucial step. It is important to remember that the soldering time for each pad must be kept very short (less than half a second) as the soldering area is extremely small, excessive heat can easily cause the pad to detach from the IC and destroying the chip in the process. So if a solder point is not done successfully, wait till it cools down before giving it a second try. It is also helpful to apply a little bit of flux on each pad prior to soldering.</p>
<p>The wire I used to connect the pads is 38 AWG <a href="http://en.wikipedia.org/wiki/Magnet_wire">magnetic wire</a>. Generally speaking anything in the neighborhood of 35 to 40 AWG should work just as well. Prior to soldering, use fine sand paper to carefully remove the thin layer of insulation. To ensure that the wire makes good contact with the pad and to reduce soldering time, the wires need to be pre-tined. A uniform layer of solder is also a good indicator of the successful removal of the insulation.</p>
<p>Start from the chip pads. Line up the tinned magnetic wire using one hand and use the solder iron tip to just touch the pad a for a split second. This is usually enough time to fuse the pre-tinned pad and magnetic wire together. Wait for a couple of seconds till the pad cools down and pull the magnetic wire gently to make sure that the soldering was done successfully. Then, solder the other end of the magnetic wire onto the perf-board and cut off the excessive wire. Repeat the above step till all pads are soldered. The finished board should look like this  (with headers):</p>
<div id="attachment_1873" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/04/accelerometer_3.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/04/accelerometer_3-300x225.jpg" alt="LIS3LV02DL on break-out board with headers" title="LIS3LV02DL on break-out board with headers" width="300" height="225" class="size-medium wp-image-1873" /></a><p class="wp-caption-text">LIS3LV02DL on break-out board with headers</p></div>
<h3>4. The finished breakout board</h3>
<p>The finished breakout board can be used as is and you can solder the remaining components onto it to finish up. Or, if you intend to use it with breadboards or sockets, you can solder headers onto the board:</p>
<div id="attachment_1880" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/04/accelerometer_4.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/04/accelerometer_4-300x225.jpg" alt="Finished LTS3LV02DL breakout board with male headers" title="Finished LTS3LV02DL breakout board with male headers" width="300" height="225" class="size-medium wp-image-1880" /></a><p class="wp-caption-text">Finished LTS3LV02DL breakout board with male headers</p></div>
<p>Using similar techniques, you can make adapters for other LGA, BGA or SSOP chips as well. In my next post, I will give some code examples on how to handle the communications between this three-axis accelerometer and an Arduino using SPI. </p>
<p>Stay tuned.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2010/04/16/interfacing-lis3lv02dl-using-spi-i/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>4 Digit 7 Segment Display Using Arduino</title>
		<link>http://www.kerrywong.com/2010/04/10/4-digit-7-segment-display-using-arduino/</link>
		<comments>http://www.kerrywong.com/2010/04/10/4-digit-7-segment-display-using-arduino/#comments</comments>
		<pubDate>Sun, 11 Apr 2010 00:14:03 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[AVR/Arduino]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[7 Segment]]></category>
		<category><![CDATA[74HC595]]></category>
		<category><![CDATA[Arduino]]></category>
		<category><![CDATA[Atmega328P]]></category>
		<category><![CDATA[AVR]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Physical Computing]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=1798</guid>
		<description><![CDATA[I was inspired by Paul&#8217;s 7 segment display and decided to build one myself. He used 4 common cathode 7 segment displays. In his original schematics, all the segments within a display shared one current limiting resistor which unfortunately affect the display brightness when different numbers of segments are lit. I happened to have two [...]]]></description>
			<content:encoded><![CDATA[<p>I was inspired by <a href="http://www.sqlskills.com/blogs/paulselec/post/Arduino-cascading-shift-registers-to-drive-7-segment-displays.aspx">Paul&#8217;s 7 segment display</a> and decided to build one myself. He used 4 common cathode 7 segment displays. In his original schematics, all the segments within a display shared one current limiting resistor which unfortunately affect the display brightness when different numbers of segments are lit. I happened to have two common anode dual 7 segment displays (QDSP-G545) so I decided to use them and four 74HC595 shift registers to build a four 7-seg display. Realizing that other people might be using either common anode or common cathode displays, I also built a library that can be used for either case.<span id="more-1798"></span></p>
<p>Without further due, here&#8217;s the schematics of the 4 digit 7 segment display (click for higher resolution pictures):</p>
<div id="attachment_1816" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/04/4_7seg.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/04/4_7seg-300x157.png" alt="4 Digit 7 Segment Display" title="4 Digit 7 Segment Display" width="300" height="157" class="size-medium wp-image-1816" /></a><p class="wp-caption-text">4 Digit 7 Segment Display</p></div>
<p>For finer controls, I left the MR OE pins (pin 10 and 13) unconnected so that they can be controlled by program. But for general use, you can connect pin 10 (MR) to Vcc and pin 13 (OE) to ground so that the output is always enabled.</p>
<p>Here&#8217;s the finished display (the letters displayed are &#8220;A.S.A.P&#8221;)</p>
<div id="attachment_1802" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/04/4dig7segdisplay.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/04/4dig7segdisplay-300x225.jpg" alt="The display in action (showing A.S.A.P.)" title="The display in action (showing A.S.A.P.)" width="300" height="225" class="size-medium wp-image-1802" /></a><p class="wp-caption-text">The display in action (showing A.S.A.P.)</p></div>
<p>It is fairly straight forward to write programs to interact with the above 4 digit display. The following C code offers a simple method disp() to display letters/digits that are predefined (see the comment section before the code and you will get an idea how to build your own symbols other than the ones included). The four boolean variables (dot1 to dot4) are used to turn on the decimal point on each segment independent of what is being displayed.</p>
<pre class="brush: cpp;">
//aaaaaa
//f    b
//fggggb
//e    c
//eddddc p

//   abcdefgp ~abcdefgp DEC	~DEC
//1  00001100  11110011 12 	243
//2  11011010  00100101 218 101
//3  11110010  00001101 242 13
//4  01100110  10011001 102	153
//5  10110110  01001001 182	73
//6  10111110  01000001 190	65
//7  11100000  00011111 224	31
//8  11111110  00000001 254	1
//9  11110110  00001001 246	9
//0  11111101  00000010 253	2
//A  11101110  00010001 238	17
//b  00111110  11000001 62	193
//c  00011010  11100101 26	229
//C  10011100  01100011 156	99
//d  01111010  10000101 122 133
//e  11011110  00100001 222 33
//E  10011110  01100001 158 97
//F  10001110  01110001 142	113
//g  11110110  00001001 246	9
//H  01101110  10010001 110	145
//h  00101110  11010001 46	209
//I  01100000  10011111 96 	159
//J  01111000  10000111 120	135
//L  00011100  11100011 28 	227
//n  00101010  11010101 42	213
//o  00111010  11000101 58	197
//P  11001110  00110001 206	49
//q  11100110  00011001 230	25
//r  00001010  11110101 10	245
//S  10110110  01001001 182 73
//t  00011110  11100001 30	225
//u  00111000  11000111 56	199
//U  01111100  10000011 124	131
//y  01110110  10001001 118	137
//-  00000010  11111101 2 	253
//-  10000000  01111111 128	127
//-  00010000  11101111 16	239
//.  00000001  11111110 1 	254
//|| 01101100  10010011 108	147
//=  10010000  01101111 144 111
//=  10000010  01111101 130 125
//=  00010010  11101101 18	237
//=- 10010010  01101101 146 109

int latchPin = 10;
int clockPin = 7;
int dataPin = 3;

//note that for common cathode displays the
//bit values are inverted (see code)
const int COMMON_ANODE = 1; //1 CA, 0 CC

struct CharMap
{
  char c;
  byte v;
};

const int cmap_len = 41;
struct CharMap cmap[] = {
{' ', 0},
{'1', 12},
{'2', 218},
{'3', 242},
{'4', 102},
{'5', 182},
{'6', 190},
{'7', 224},
{'8', 254},
{'9', 246},
{'0', 253},
{'A', 238},
{'b', 62},
{'c', 26},
{'C', 156},
{'d', 122},
{'e', 222},
{'E', 158},
{'F', 142},
{'g', 246},
{'H', 110},
{'h', 46},
{'I', 96},
{'J', 120},
{'L', 28},
{'n', 42},
{'o', 58},
{'P', 206},
{'q', 230},
{'r', 10},
{'S', 182},
{'t', 30},
{'u', 56},
{'U', 124},
{'y', 118},
{'-', 2},
{'~', 128},
{'_', 16},
{'.', 1},
{'|', 108},
{'=', 144}
};

byte getCode(char c)
{
  byte r = 2;

  for (int i = 0 ; i &lt; cmap_len ; i++) {
    if (c == cmap[i].c) {
      r = cmap[i].v;
      break;
    }
  }

  return r;
}

//display c1 c2 c3 c4
//Note the boolean values for dot1 dot2 dot3 and dot4
//indicates whether or not to show the decimal point
void disp(char c1, bool dot1, char c2, bool dot2, char c3, bool dot3, char c4, bool dot4)
{
  byte b1 = getCode(c1);
  byte b2 = getCode(c2);
  byte b3 = getCode(c3);
  byte b4 = getCode(c4);

  if (dot1 == true) b1 += 1;
  if (dot2 == true) b2 += 1;
  if (dot3 == true) b3 += 1;
  if (dot4 == true) b4 += 1;

  if (COMMON_ANODE == 1) {
    b1 = 255 - b1;
    b2 = 255 - b2;
    b3 = 255 - b3;
    b4 = 255 - b4;
  } 

  digitalWrite(latchPin, LOW);        

  shiftOut(dataPin, clockPin,  b4);
  shiftOut(dataPin, clockPin,  b3);
  shiftOut(dataPin, clockPin,  b2);
  shiftOut(dataPin, clockPin,  b1);

  digitalWrite(latchPin, HIGH);
}

void setup7seg()
{
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);

  disp(' ', false, ' ', false, ' ', false, ' ', false);
}

void shiftOut(uint8_t dataPin, uint8_t clockPin, byte val)
{
	int i;

	for (i = 0; i &lt; 8; i++)  {
		digitalWrite(dataPin, (val &amp; _BV(i)));
                delayMicroseconds(10);
		digitalWrite(clockPin, HIGH);
                delayMicroseconds(10);
		digitalWrite(clockPin, LOW);
                delayMicroseconds(10);
	}
}

void setup()
{
  setup7seg();
}

void loop()
{
  disp('d',false,'I',false,'S',false,'C',false); //displays the word dISC
  delay(1000);
}
</pre>
<p>The shiftOut method is actually included in standard Arduino libraries, the reason I included it in my code is that I had to add slight delay between each digitalWrite otherwise the output is not always correct. I suspect this is due to the long wiring I used on the circuit board. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2010/04/10/4-digit-7-segment-display-using-arduino/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>On ATMega328 Bootloading With FTDI Bitbang Method</title>
		<link>http://www.kerrywong.com/2010/04/02/on-atmega328-bootloading-with-ftdi-bitbang-method/</link>
		<comments>http://www.kerrywong.com/2010/04/02/on-atmega328-bootloading-with-ftdi-bitbang-method/#comments</comments>
		<pubDate>Sat, 03 Apr 2010 01:58:11 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[AVR/Arduino]]></category>
		<category><![CDATA[Arduino]]></category>
		<category><![CDATA[Atmega328P]]></category>
		<category><![CDATA[AVR]]></category>
		<category><![CDATA[Bootloader]]></category>
		<category><![CDATA[Ubuntu 64bit]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=1759</guid>
		<description><![CDATA[I have been using the FTDI bitbang method piloted by Kimio Kosaka and improved by others (1,2,3) to flash Arduino bootloader onto blank ATMega328p for a while and thought I would share my experience with everyone. The reason to use Kimio&#8217;s method is that no separate AVR programmer is needed as this method essentially turns [...]]]></description>
			<content:encoded><![CDATA[<p>I have been using the <a href="http://www.ftdichip.com/Documents/AppNotes.htm">FTDI bitbang</a> method piloted by <a href="http://www.geocities.jp/arduino_diecimila/bootloader/index_en.html">Kimio Kosaka</a> and improved by others (<a href="http://labs.coffeebot.net/content/ftdi-drivers-avrdude-linux">1</a>,<a href="http://itpedia.nyu.edu/wiki/Bootloading_the_Arduino--Using_Only_the_Arduino!">2</a>,<a href="http://doswa.com/blog/2009/12/20/avrdude-58-with-ftdi-bitbang-patch-on-linux/">3</a>) to flash Arduino bootloader onto blank ATMega328p for a while and thought I would share my experience with everyone.<span id="more-1759"></span></p>
<p>The reason to use Kimio&#8217;s method is that no separate AVR programmer is needed as this method essentially turns the Arduino board (the FTDI module on the Arduino board to be precise) into an AVR writer (for more information, please see articles listed <a href="http://www.arduino.cc/playground/Hacking/AvrdudeFTDIBitbang">here</a> on the Arduino site.) </p>
<p>There seems to be another method (<a href="http://arduino.cc/en/Tutorial/ArduinoISP">ArduinoISP</a>) that could be used to burn bootloaders onto blank MCUs but I haven&#8217;t been able to use it successfully. My understanding is that this method is similar to the FTDI bitbang method in that it generates the signals necessary to burn the bootloader via software. The main difference is that instead of programming the ft232r chip,  this method generates the signaling via the MCU itself. The advantage is that no code changes and recompilation is necessary. I am not sure if anyone has had any luck with this method. So please post your detailed step-by-step instructions if you managed to get it to work.</p>
<p>Anyway, I am using Ubuntu 9.10 64 bit. And following the excellent directions mentioned by <a href="http://labs.coffeebot.net/content/ftdi-drivers-avrdude-linux">Nate</a> and <a href="http://doswa.com/blog/2009/12/20/avrdude-58-with-ftdi-bitbang-patch-on-linux/">David</a>, I got the FTDI bitbang method working on both avrdude 5.3.1 and avrdude 5.10.</p>
<p>There are a lot of variations of commands (covered in the references I listed above) that you can use to invoke avrdude to flash bootloader. Here&#8217;s the command I use to burn the bootloader (assuming you are within the directory where you have the FTDI bitbang patched avrdude. The bootloader HEX file and the configuration file are also in the same directory from which avrdude is launched). Note that the baud-rate is defaulted to 115200.</p>
<blockquote><p>
sudo ./avrdude -C avrdude.conf -c duemilanove  -p m328p -u -U lock:w:0x3f:m -U efuse:w:0&#215;05:m -U hfuse:w:0xDA:m -U lfuse:w:0xFF:m -U flash:w:ATmegaBOOT_168_atmega328.hex -U lock:w:0x0f:m
</p></blockquote>
<p>And here&#8217;s the sample output for a successful run:</p>
<blockquote><p>
avrdude: BitBang OK<br />
avrdude: pin assign miso 3 sck 5 mosi 6 reset 7<br />
avrdude: drain OK</p>
<p> ft245r:  bitclk 230400 -> ft baud 115200<br />
avrdude: AVR device initialized and ready to accept instructions</p>
<p>Reading | ################################################## | 100% 0.00s</p>
<p>avrdude: Device signature = 0x1e950f<br />
avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed<br />
         To disable this feature, specify the -D option.<br />
avrdude: erasing chip<br />
 ft245r:  bitclk 230400 -> ft baud 115200<br />
avrdude: reading input file &#8220;0x3f&#8221;<br />
avrdude: writing lock (1 bytes):</p>
<p>Writing | ################################################## | 100% 0.02s</p>
<p>avrdude: 1 bytes of lock written<br />
avrdude: verifying lock memory against 0x3f:<br />
avrdude: load data lock data from input file 0x3f:<br />
avrdude: input file 0x3f contains 1 bytes<br />
avrdude: reading on-chip lock data:</p>
<p>Reading | ################################################## | 100% 0.02s</p>
<p>avrdude: verifying &#8230;<br />
avrdude: 1 bytes of lock verified<br />
avrdude: reading input file &#8220;0&#215;05&#8243;<br />
avrdude: writing efuse (1 bytes):</p>
<p>Writing | ################################################## | 100% 0.02s</p>
<p>avrdude: 1 bytes of efuse written<br />
avrdude: verifying efuse memory against 0&#215;05:<br />
avrdude: load data efuse data from input file 0&#215;05:<br />
avrdude: input file 0&#215;05 contains 1 bytes<br />
avrdude: reading on-chip efuse data:</p>
<p>Reading | ################################################## | 100% 0.02s<br />
avrdude: verifying &#8230;<br />
avrdude: 1 bytes of efuse verified<br />
avrdude: reading input file &#8220;0xDA&#8221;<br />
avrdude: writing hfuse (1 bytes):</p>
<p>Writing | ################################################## | 100% 0.02s</p>
<p>avrdude: 1 bytes of hfuse written<br />
avrdude: verifying hfuse memory against 0xDA:<br />
avrdude: load data hfuse data from input file 0xDA:<br />
avrdude: input file 0xDA contains 1 bytes<br />
avrdude: reading on-chip hfuse data:</p>
<p>Reading | ################################################## | 100% 0.02s</p>
<p>avrdude: verifying &#8230;<br />
avrdude: 1 bytes of hfuse verified<br />
avrdude: reading input file &#8220;0xFF&#8221;<br />
avrdude: writing lfuse (1 bytes):</p>
<p>Writing | ################################################## | 100% 0.02s</p>
<p>avrdude: 1 bytes of lfuse written<br />
avrdude: verifying lfuse memory against 0xFF:<br />
avrdude: load data lfuse data from input file 0xFF:<br />
avrdude: input file 0xFF contains 1 bytes<br />
avrdude: reading on-chip lfuse data:</p>
<p>Reading | ################################################## | 100% 0.02s</p>
<p>avrdude: verifying &#8230;<br />
avrdude: 1 bytes of lfuse verified<br />
avrdude: reading input file &#8220;ATmegaBOOT_168_atmega328.hex&#8221;<br />
avrdude: input file ATmegaBOOT_168_atmega328.hex auto detected as Intel Hex<br />
avrdude: writing flash (32670 bytes):</p>
<p>Writing | ################################################## | 100% 17.72s</p>
<p>avrdude: 32670 bytes of flash written<br />
avrdude: verifying flash memory against ATmegaBOOT_168_atmega328.hex:<br />
avrdude: load data flash data from input file ATmegaBOOT_168_atmega328.hex:<br />
avrdude: input file ATmegaBOOT_168_atmega328.hex auto detected as Intel Hex<br />
avrdude: input file ATmegaBOOT_168_atmega328.hex contains 32670 bytes<br />
avrdude: reading on-chip flash data:</p>
<p>Reading | ################################################## | 100% 8.08s</p>
<p>avrdude: verifying &#8230;<br />
avrdude: 32670 bytes of flash verified<br />
avrdude: reading input file &#8220;0x0f&#8221;<br />
avrdude: writing lock (1 bytes):</p>
<p>Writing | ################################################## | 100% 0.05s</p>
<p>avrdude: 1 bytes of lock written<br />
avrdude: verifying lock memory against 0x0f:<br />
avrdude: load data lock data from input file 0x0f:<br />
avrdude: input file 0x0f contains 1 bytes<br />
avrdude: reading on-chip lock data:</p>
<p>Reading | ################################################## | 100% 0.02s</p>
<p>avrdude: verifying &#8230;<br />
avrdude: 1 bytes of lock verified</p>
<p>avrdude done.  Thank you.</p>
</blockquote>
<p>The bootloading process is extremely fast and takes only around a minute to finish.</p>
<p>One thing I found that you need to pay special attention to is that if you are flashing bootloader onto a brand new ATMega328p chip (i.e. it hasn&#8217;t been bootloaded before), you will need to do it at a slower baud rate and if you use the above command you will get the following error message:</p>
<blockquote><p>
avrdude: BitBang OK<br />
avrdude: pin assign miso 3 sck 5 mosi 6 reset 7<br />
avrdude: drain OK</p>
<p> ft245r:  bitclk 230400 -> ft baud 115200<br />
avrdude: ft245r_program_enable: failed<br />
avrdude: initialization failed, rc=-1<br />
         Double check connections and try again, or use -F to override<br />
         this check.
</p></blockquote>
<p>If you add the -F switch as suggested by the error message, you will receive this error instead:</p>
<blockquote><p>
avrdude: BitBang OK<br />
avrdude: pin assign miso 3 sck 5 mosi 6 reset 7<br />
avrdude: drain OK</p>
<p> ft245r:  bitclk 230400 -> ft baud 115200<br />
avrdude: ft245r_program_enable: failed<br />
avrdude: initialization failed, rc=-1<br />
avrdude: AVR device initialized and ready to accept instructions<br />
avrdude: Device signature = 0&#215;000000<br />
avrdude: Yikes!  Invalid device signature.<br />
avrdude: Expected signature for ATMEGA328P is 1E 95 0F<br />
avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed<br />
         To disable this feature, specify the -D option.
</p></blockquote>
<p>After some investigation, I found out that when bootloading a new chip, the -B parameter is mandatory. The following command (with -B setting) can be used in this case:</p>
<blockquote><p>
sudo ./avrdude -C avrdude.conf -c duemilanove  -p m328p -B 1.0 -u -U lock:w:0x3f:m -U efuse:w:0&#215;05:m -U hfuse:w:0xDA:m -U lfuse:w:0xFF:m -U flash:w:ATmegaBOOT_168_atmega328.hex -U lock:w:0x0f:m
</p></blockquote>
<p>But with the -B 1.0 parameter, the flashing process is significantly slower as the baud rate is automatically set to 2400 and it would take about 6 minutes for the whole process to finish.</p>
<blockquote><p>
avrdude: BitBang OK<br />
avrdude: pin assign miso 3 sck 5 mosi 6 reset 7<br />
avrdude: drain OK</p>
<p> ft245r:  bitclk 4800 -> ft baud 2400<br />
avrdude: AVR device initialized and ready to accept instructions</p>
<p>&#8230;
</p></blockquote>
<p>After some research, it turned out that only the fuse and lock bit settings need to be done at a slower baud rate for new chips. Thus, you can split the command into the following two commands (the first one set the fuse and lock at the slow baud rate, the second one burns the bootloader at the higher baud rate) to speed things up:</p>
<blockquote><p>
sudo ./avrdude -C avrdude.conf -c duemilanove  -p m328p -B 1.0 -u -U lock:w:0x3f:m -U efuse:w:0&#215;05:m -U hfuse:w:0xDA:m -U lfuse:w:0xFF:m </p>
<p>sudo ./avrdude -C avrdude.conf -c duemilanove  -p m328p -u -U flash:w:ATmegaBOOT_168_atmega328.hex -U lock:w:0x0f:m
</p></blockquote>
<p>So in summary, you can use the above two commands to load bootloaders onto either new chips or chips that already have bootloaders on them. Use the following command on chips that are previously bootloaded only if you want a succinct command:</p>
<blockquote><p>
sudo ./avrdude -C avrdude.conf -c duemilanove -p m328p -u -U lock:w:0×3f:m -U efuse:w:0×05:m -U hfuse:w:0xDA:m -U lfuse:w:0xFF:m -U flash:w:ATmegaBOOT_168_atmega328.hex -U lock:w:0×0f:m
</p></blockquote>
<p><i>Update:</i><br />
It seems that someone had managed to get the <a href="http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1267120897">Arduino as ISP function working</a>, but I haven&#8217;t tried it yet.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2010/04/02/on-atmega328-bootloading-with-ftdi-bitbang-method/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>A Simple Dual H-Bridge</title>
		<link>http://www.kerrywong.com/2010/03/22/a-simple-dual-h-bridge/</link>
		<comments>http://www.kerrywong.com/2010/03/22/a-simple-dual-h-bridge/#comments</comments>
		<pubDate>Tue, 23 Mar 2010 00:26:37 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[AVR/Arduino]]></category>
		<category><![CDATA[Arduino]]></category>
		<category><![CDATA[Atmega328P]]></category>
		<category><![CDATA[AVR]]></category>
		<category><![CDATA[H-Bridge]]></category>
		<category><![CDATA[Physical Computing]]></category>
		<category><![CDATA[Stepper Motor]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=1733</guid>
		<description><![CDATA[H-bridge is frequently used to control DC motors and stepper motors. When controlling a bipolar stepper motor, two full H-bridges are needed. There are many H-bridge ICs (like L298, MPC17529 and SN754410 which is a quad half H-bridge) for just that purpose. But if you are on a budget, you may want to consider building [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://en.wikipedia.org/wiki/H-bridge">H-bridge</a> is frequently used to control DC motors and stepper motors. When controlling a <a href="http://en.wikipedia.org/wiki/Stepper_motor">bipolar stepper motor</a>, two full H-bridges are needed. There are many H-bridge ICs (like <a href="http://www.st.com/stonline/books/pdf/docs/1773.pdf">L298</a>, <a href="http://www.freescale.com/files/analog/doc/data_sheet/MPC17529.pdf">MPC17529</a> and <a href="http://focus.ti.com/lit/ds/symlink/sn754410.pdf">SN754410</a> which is a quad half H-bridge) for just that purpose. But if you are on a budget, you may want to consider building a dual H-bridge yourself.<span id="more-1733"></span></p>
<p>The following schematic shows a simple dual H-bridge using eight general purpose transistors (<a href="http://www.fairchildsemi.com/ds/2N%2F2N3904.pdf">2N3904</a> and <a href="http://www.fairchildsemi.com/ds/2N/2N3906.pdf">2N3906</a>). Given the maximum <em>Iceo</em> of roughly 200mA, this circuit can be used to drive a small bipolar stepper motor operating between 5V and 12V, such as the stepper motors found in most floppy drives and CD/DVD drives. </p>
<div id="attachment_1741" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/03/dualhbridge.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/03/dualhbridge-300x209.png" alt="A Dual H-bridge" title="A Dual H-bridge" width="300" height="209" class="size-medium wp-image-1741" /></a><p class="wp-caption-text">A Dual H-bridge</p></div>
<p>The four control inputs (1,2,3,4) can be driven with <a href="http://arduino.cc">Arduino</a>&#8216;s digital pins (i.e. 2,3,4,5) directly. The following program illustrates how to signal the four leads of a bipolar stepper motor for it to rotate. Of course, there&#8217;s already a <a href="http://www.arduino.cc/en/Reference/Stepper">stepper motor library</a> built for this purpose. The program below is helpful when learning the sequence of the pulses required by bipolar stepper motors.</p>
<pre class="brush: cpp;">
int coila1 = 2;
int coila2 = 3;
int coilb1 = 4;
int coilb2 = 5;

void setup()
{
  pinMode(coila1, OUTPUT);
  pinMode(coila2, OUTPUT);
  pinMode(coilb1, OUTPUT);
  pinMode(coilb2, OUTPUT);
}

void loop()
{
  digitalWrite(coila1, HIGH);
  digitalWrite(coila2, LOW);
  digitalWrite(coilb1, LOW);
  digitalWrite(coilb2, LOW);
  delay(10);

  digitalWrite(coila1, LOW);
  digitalWrite(coila2, LOW);
  digitalWrite(coilb1, HIGH);
  digitalWrite(coilb2, LOW);
  delay(01);

  digitalWrite(coila1, LOW);
  digitalWrite(coila2, HIGH);
  digitalWrite(coilb1, LOW);
  digitalWrite(coilb2, LOW);
  delay(10);

  digitalWrite(coila1, LOW);
  digitalWrite(coila2, LOW);
  digitalWrite(coilb1, LOW);
  digitalWrite(coilb2, HIGH);
  delay(10);
}
</pre>
<p>Here is a picture of an Arduino controlled CD-ROM stepper motor (the one controlling the tray mechanism) powered by the above dual H-bridge (with an added LED for power).</p>
<div id="attachment_1745" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/03/arduinobipolarmotor.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/03/arduinobipolarmotor-300x175.jpg" alt="A CD-ROM stepper motor driven by Arduino" title="A CD-ROM stepper motor driven by Arduino" width="300" height="175" class="size-medium wp-image-1745" /></a><p class="wp-caption-text">A CD-ROM stepper motor driven by Arduino</p></div>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2010/03/22/a-simple-dual-h-bridge/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
