Wednesday, July 07, 2010

PID Codes and Algorithms Line Follower

PID Implementation On Microcontrollers


A PID Controller is a common technique used to control a wide variety of machinery including vehicles, robots and even rockets. The complete mathematical description of a PID Controller is fairly complex but a much simpler understanding is really all that is needed to use a PID effectively.

This document is a description of how to create a PID Controller for use with Lego Mindstorms Robots using the NXT-G programming language.

It will be easier if we have an actual task in mind so I will describe how to create a PID to do line following. Once created, the same PID can be used, with only minor modifications, with any other Mindstorms application such as getting a robot that can drive as straight as possible, or even for a robot that can balance with nothing but 2 wheels touching the ground like a Segway.

A PID is really pretty straight forward and the typical description of a PID is easily understood by anyone that has had Calculus. This document is targeted towards First Lego League kids in third through eighth grade. Since there aren't many kids that have had Calculus I'll try to build the whole concept up from a very simple starting point without using any Calculus.Basic_bot.

So lets start with the basic layout of a robot that would be suitable for line following. At the right is a simplified drawing of a top view of the robot with all the details we need. The robot is a differential steer robot with two motors, each connected to one of the wheels A and C. The robot has a light sensor mounted at the front that points straight down so it sees nothing but the mat (floor, ground, table top, whatever the robot is on). The red circle represents the fairly small spot on the mat that the light sensor can actually "see". The rest of the robot is the large rectangle with an arrow, the arrow shows the normal direction of travel.

Our goal is to get the robot to follow the fat black line. Line following is a basic robotic behavior and is often one of the first things people learn. A mobile device that can follow a line displays all the characteristics of a true robot. It uses sensor to gather information about the world around it and changes it's behavior depending upon that information.

Line followers can be built with one light sensor, or two, or a dozen or however many you happen to have. In general, the more light sensors you have the better you can follow a line. Here we'll limit ourselves to a single Mindstorms light sensor. Even with a single sensor we should be able to build a robot that can track the line very precisely even if the line has curves in it. The thing you usually loose with a single sensor is the ability to follow the line while moving fast. Often, the more sensors you have the faster the robot can move while it follows the line.

The first trick we'll use, which is unrelated to a PID, is that we won't try to actually follow the line. Instead, we'll try to follow the edge of the line. Why? Because if we follow the line itself (the black) then when the robot drifts off the line and the sensor "sees white" we don't know which side of the line we are on. Are we left or right of the line? If we follow the line's edge then we can tell which way we are off the edge as the robot drifts off the line. If the light sensor "sees white" then we know it is left of the line's edge (and the line). If it "sees black" then we know it is to the right of the line's edge (and on the line). This is called a "left hand line follower" since it is following the line's left edge.

We need to know what values the light sensor returns when it "sees white" and when it "sees black". A typical uncalibrated sensor might give a "white" reading of 50 and a "black" reading of 40 (uncalibrated, on a 0 to 100 scale). It is convenient to draw the values on a simple number line to help visualize how we convert light sensor values into changes in the robot's movement. Below are our made up light values for white and black.

light_number_line

We'll just divide the range into two equal pieces and say that if the light level is less than 45 we want the robot to turn left. If it is greater than 45 we want to turn right. I won't go into how exactly the turns should be done. I'll just say that gentle turns work well for a fairly straight line. A line with lots of curves usually needs to be making sharper turns. For gentle turns you might use Power levels of 50% on the fast wheel and 20% on the slow wheel. For sharper turns on a curvy line you might need to use 30% power for the fast wheel and coast or brake the slow wheel. Whatever power levels you use the numbers will be the same for the two turns, you just switch which motor gets the big number and which get the smaller number (or a stop command).

This type of a line follower will follow a line but it isn't very pretty. It looks OK on a straight line with with the motors programmed for gentle turns. But if the line has any curves then you have tell the robot to use sharper turns to follow line. That makes the robot swing back and forth across the line. The robot only "knows" how to do two things; turn left and turn right. This approach can be made to work but it is not very fast or accurate and looks terrible.

In the above approach the robot never drives straight, even if it is perfectly aligned with line's edge and the line is straight. That doesn't seem very efficient does it?

Lets try to fix that. Instead of dividing our light value number line into two regions lets divide it into three.
light_number_line_2

So now if the light level is less than 43 we want the robot to turn left. If the light value is between 44 and 47 we want it to go straight (zoom zoom). If the light level is greater than 47 we want to turn right. This can be easily be implemented in Mindstorms NXT-G with a switch (yes/no) within a switch. You actually only have to do two tests not three.

This approach works better than the first one. At least now the robot is sometimes moving straight forward. As with the first approach you still have to decide what kinds of turns you need and that usually depends on the characteristics of the line you are following. The robot will probably still hunt back a forth a fair amount.

The astute reader will probably have thought "well if three light ranges are better than two than what about adding even more?" That is the beginning of a PID.

The "P" in "PID": Proportion(al) is the key

So what will happen if we add more divisions to our light scale line? Well the first thing we have to deal with is what does "turn" mean with more than three light ranges? In our first approach the robot could do just two things, turn left or right. The turns were always the same just in opposite directions. In the second approach we added the "go straight" to the two turns. If we have more than three ranges then we need more "kinds" of turns.

To help understand "more kinds of turns" we will redo or number line a bit and convert it into a graph. Our X-axis (horizontal) will be our light values just like on the number lines. The Y-axis (vertical) well be our "turn" axis.

On the left is our original two level setup expressed on a graph. The robot can only do two things (shown by the blue lines), turn right or left and the turns are always the same except for their direction. In the center is the three level follower. The added center range is where the robot drives straight (Turn=0). The turns are the same as before. On the right is a Proportional line follower. In a proportional line follower the turn varies smoothly between two limits. If the light sensor reading says we are close to the line then we do a small turn. If we are far from the line then we do a big turn. Proportional is an important concept. Proportional means there is a linear relationship between two variables. To put it even simpler, proportional means a graph of the variables against each other produces a straight line (as in the right hand graph above).

As you may know, the equation of a straight line is:

y = mx + b

Where y is the distance up (or down) the Y-axis, x the distance on the X-axis, m is the slope of the line and b is the Y intercept, the point where the line crosses the Y-axis when x is zero. The slope of the line is defined as the change in the y value divided by the change in the x value using any pair of points on the line.

If you don't know much about lines (or have forgotten what you once new) I'll expand a bit and make some simplifications to our graph and equation. First, we will shift the center of our light number line (the X-axis) to zero. That's easy to do. For our 40 and 50 light value range we just subtract 45 (that's the average of 40 and 50, (40+50)/2 ) from all of our light readings. We will call that result the error. So, if the light value is 47 we subtract 45 and get an error=2. The error tells us how far off the line's edge we are. If the light sensor is exactly on the line's edge our error is zero since the light value is 45 and we subtract 45 from all of our readings. If the sensor is all the way out into the white our error is +5. All the way into the black the error is -5.

In the above graph I have shifted the axis by converting it to an error scale. Since the line now crosses the Y-axis at zero that mens b is is zero and the equation for the line is a bit simpler;

y = mx

or using our labels

Turn = m*error

We haven't yet defined what the turn axis means so for now we will just say the turns range from -1 (hard turn to the left) to +1 (hard turn to the right) and a zero turn means we are going straight. The slope of the line in the graph above can be calculated using the two points marked in red (any two points on the line will work);

slope = m = (change in y)/(change in x) = ( 1- (-1)) / (-5 - 5 ) = 2/10 = 0.2

The slope is a proportionality constant and is the factor that you have to multiply the error (x value) by to convert it into a Turn (y value). That's an important thing to remember.

The "slope" has a couple names that all mean the same thing, at least in this context. In the PID literature slopes (proportionality constants, m in the equation of a line) are called "K" (from misspelling of the word "constant"?). Various Ks show up all over the PID literature and are a very important. You can think of a K (or m or slope or proportionality constant) as a conversion factor. You use K to convert a number that means one thing (light values or error in our case) into something else like a turn. That's all that a K does. Very simple and very powerful.

So using these new names for our variables the equation of the line is;

Turn = K*(error)

In words that's "take the error and multiply it by the proportionality constant K to get the needed turn. The value Turn is the output of our P controller and is called the "P term" since this is only a proportional controller.

You may have noticed that in the last graph the line does not extend outside the error range of -5 to +5. Outside the range of -5 to +5 we can't tell how far the sensor is from the line. All "white" looks the same once the sensor can't see any black at all. Remember that this range is arbitrary, your range will be determined by you light sensor setup, the colors of the mat etc. Once the light sensor gets too far from the line edge it starts to give a constant reading, that means the light sensor reading is no longer proportional to the error. We can only judge how far the sensor is from the line's edge when the sensor is actually pretty close to it. Over that narrow range the light sensor reading is proportional to the distance. So our sensor setup has a limited range over which it gives proportional information. Outside that range it tells us the correct direction but the magnitude (size) is wrong. The light sensor reading, or the error, is smaller than it should be and doesn't give as good an idea of what the turn should be to fix the error.

In the PID literature the range over which the sensor gives a proportional response is called the "proportional range" (go figure :D ). The proportional range is another very important concept in PIDs. In our line follower the proportional range for the light sensor is 40 to 50, for the error it is -5 to +5. Our motors also have a proportional range, from -100 (full power backwards) to +100 (full power forwards). I'll just say a couple things about it the importance of the proportional range:

(1) You want the proportional range to be as wide as possible. Our light sensor's proportional range is pretty small, that is, the sensor has to be pretty close to the line edge to get proportional information. Exactly how wide the range is depends mostly on how high the sensors is above the mat. If the sensor is very close to the mat, say 1/16 inch, then the sensor is seeing a very small circle on the mat. A small side to side movement of the light sensor will swing the error from -5 to +5, that's all the way through our proportional range. You might say the sensor has "tunnel vision" and it can only see a very small part of the mat. The sensor has to be very close to the line edge to get a reading that isn't either "white" or "black". If the sensor is moved higher off the mat then it sees a larger circle on the mat. At a height of about 1/2 inch the light sensor appears to be looking at a circle on the mat that is about 1/2 inch across. With the sensor up this high the proportional range is much wider, since the light sensor only needs to stay within +/- 1/2 inch of the line edge to maintain a proportional output. Unfortunately, there are two drawbacks to a high light sensor. First, a high light sensor "sees", and responds to, the room lights much more than a low sensor. A high sensor also has less difference between black and white than a low sensor. At a sufficiently large distance black and white will give the same reading.

(2) Outside the proportional range the controller will move things in the correct direction but it will tend to under correct. The controller's proportional response is limited by the proportional range.

From P to actual motor power levels

How can we implement the turns? What should the actual motor power levels be? One way to do the turns is to define a "Target power level", which I'll call "Tp". Tp is the power level of both motors when the robot is supposed to go straight ahead, which it does when the error=0. When the error is not zero we use the equation Turn = K*(error) to calculate how to change the power levels for the two motors. One motor will get a power level of Tp+Turn, the other motor will get a power level of Tp-Turn. Note that since our error is -5 to +5 that means Turn can be either positive or negative which corresponds to turns in opposite directions. It turns out that that is exactly what we want since it will automatically set the correct motor as the fast motor and the other one as the slow motor. One motor (we'll assume it is the motor on the left of the robot plugged into port A) will always get the Tp+Turn value as it's power level. The other motor (right side of robot, port C) will always get Tp-Turn as it's power level. If error is positive then Turn is positive and Tp+Turn is greater than Tp and the left motor speeds up while the right motor slows down . If the error changes sign and becomes negative (meaning we have crossed over the line's edge and are "seeing black") then Tp+Turn is now less than Tp and the left motor slows down and the right motor speeds up since Tp-Turn is greater than Tp. (Remember that the negative of a negative is a positive). Simple eh? Hopefully it'll be a bit clearer as we go on.

Pseudo Code for a P Controller

First we need to measure the values the light sensor returns for white and black. From those two number we can calculate the offset, that is, how much to subtract from a raw light reading to convert it to an error value. The offset is just the average of the white and black readings. For simplicity I'll assume that the offset has already been measured and stored in a variable called offset. (A nice upgrade would be to have the robot measure the white and black levels and calculate the offset.)

We will also need a storage location for the K constant, we'll call that Kp (the Konstant for the proportional controller). And, an initial guess as to what Kp should be. There are a lot of ways to get that first Kp value. You can guess and then refine it by trial and error. Or, you can try to estimate a value based on the characteristics of the sensor and robot. We'll do the latter. We will use a Tp (target power) of 50, when the error is zero both motors will run at power level 50. The error ranges from -5 to +5. We'll guess that we want the power to go from 50 to 0 when the error goes from 0 to -5. That means the Kp (the slope remember, the change in y divided by the change in x) is;

Kp = (0 - 50)/(-5 - 0) = 10.

We will use the Kp=10 value to convert an error value into a turn value. In words our conversion is "for every 1 unit change in the error we will increase the power of one motor by 10". The other motor's power gets decreased by 10.

So, in pseudo code ("pseudo code" means this isn't actual NXT-G, or any other type of program code, instead it is just a detailed listing of what we want the program to do):

Kp = 10                               ! Initialize our three variables
offset = 45
Tp = 50
Loop forever
LightValue = read light sensor ! what is the current light reading?
error = LightValue - offset ! calculate the error by subtracting the offset
Turn = Kp * error ! the "P term", how much we want to change the motors' power
powerA = Tp + Turn ! the power level for the A motor
powerC = Tp - Turn ! the power level for the C motor
MOTOR A direction=forward power=powerA ! issue the command with the new power level in a MOTOR block
MOTOR C direction=forward power=powerC ! same for the other motor but using the other power level
end loop forever ! done with this loop, go back to the beginning and do it again

That's it, well almost. There is a subtle problem that should be corrected. But give it a try anyway. If your robot appears to avoid the line edge, instead of trying to find it, the most likely cause is that you have swapped the turn directions. Change Kp to -10 and see what happens. If that fixes the turn directions then change Kp back to +10 and change the signs in the two power lines to;

powerA = Tp - Turn
powerC = Tp + Turn

There are two "tunable parameters" and one constant in this P controller. The constant is the offset value (the average of white and black light sensor readings). You'll need to write a short program to measure the light levels on your mat with your robot. You need a "black" and a "white" value. Calculate the average and put it into the P controller program in the offset variable. Almost all line followers require that you (or code written by you and executed by the robot) do this step.

The Kp value and the target power Tp are the tunable parameters. A tunable parameter has to be determined by trial and error. Kp controls how fast the controller will try to get back to the line edge when it has drifted away from it. Tp controls how fast the robot is moving along the line.

If the line is pretty straight you can use a large Tp to get the robot running at high speed and a small Kd so the turns (corrections) are gentle.

If the line has curves, especially sharp ones, there will be a maximum Tp value that will work. If Tp is bigger than that maximum it won't matter what Kp is, the robot will loose the line when it encounters a curve because it is moving too fast. If Tp is really small then almost any Kp value will work since the robot will be moving very slowly. The goal is to get the robot moving as fast as possible while still being able to follow the line of interest.

We had guesstimated a starting value for Kp of 10. For Tp you might start at even lower than suggested above, perhaps 15 (the robot will be moving pretty slow). Try it and see how it works. If you loose the line because the robot seems to turn sluggishly then increase Kp by a couple and try again. If you loose the line because the robot seems hyperactive in hunting back and forth for the line then decrease Kp. If the robot seems to follow the line pretty well then increase Tp and see if you can follow the line at the faster speed. For each new Tp you will need to determine a new Kp, though Kp usually won't change too much.

Following a straight line is usually pretty easy. Following a line with gentle curves is a bit harder. Following a line with sharp curves is the hardest. If the robot is moving slow enough then almost any line can be followed, even with a very basic controller. We want to get good line following, good speed and the ability to handle gentle corners. (Lines with sharp corners usually ta

Tuesday, July 06, 2010

Serial Port Interface Communication (SPI)

Theory of Operation

The Serial Peripheral Interface Bus or SPI bus is a synchronous serial data link used to communicate between two or more microcontroller and devices supporting SPI mode data transfer. Devices communicate in master/slave mode where the master device initiates the data frame. Multiple slave devices are allowed with individual slave select (chip select) lines.

This communication protocol consists of folliwng lines or pins,

  1. MOSI : Master Out Slave In (Tx for Master and Rx for Slave)
  2. MISO : Master In Slave Out (Rx for Master Tx for Slave)
  3. SCK : Serial Clock (Clock line)
  4. SS : Slave Select (To select Slave chip) (if given 0 device acts as slave)

Master: This device provides the serial clock to the other device for data transfer. As a clock is used for the data transfer, this protocol is Synchronous in nature. SS for Master will be disconnected.

Slave: This device accepts the clock from master device. SS for this has to be made 0 externally.

avr spi

avr spi













Setting up SPI in Microcontroller

avr spi

Master Microcontroller

Open Code Wizard and go to SPI tab. Enable SPI and choose Master in SPI Type.

Select clock rate depending upon your data transfer speed requirement.

Keep other settings as default.

avr spi

Slave Microcontroller

Open Code Wizard and go to SPI tab. Enable SPI and choose Slave in SPI Type.

Select clock rate depending upon your data transfer speed requirement.

Keep other settings as kept in the master microcontroller.

Data Transfer Functions

You can transmit or receive 1 byte of data at a time.

Transmit Data

spi(1 byte data);

Example: spi(‘A’);

Receive Data

c = spi(0); // c is 1 byte variable

Example: char c = spi(0);

Interrupts

Interrupt

An interrupt is a signal that stops the current program forcing it to execute another program immediately. The interrupt does this without waiting for the current program to finish. It is unconditional and immediate which is why it is called an interrupt.avr interrupt

The whole point of an interrupt is that the main program can perform a task without worrying about an external event.

For example if you want to read a push button connected to one pin of an input port you could read it in one of two ways either by polling it or by using interrupts.

Polling

Polling is simply reading the button input regularly. Usually you need to do some other tasks as well e.g. read an RS232 input so there will be a delay between reads of the button. As long as the delays are small compared to the speed of the input change then no button presses will be missed.

If however you had to do some long calculation then a keyboard press could be missed while the processor is busy. With polling you have to be more aware of the processor activity so that you allow enough time for each essential activity.

Hardware Interrupt

By using a hardware interrupt driven button reader the calculation could proceed with all button presses captured. With the interrupt running in the background you would not have to alter the calculation function to give up processing time for button reading.

The interrupt routine obviously takes processor time – but you do not have to worry about it while constructing the calculation function.

You do have to keep the interrupt routine small compared to the processing time of the other functions - it’s no good putting tons of operations into the ISR. Interrupt routines should be kept short and sweet so that the main part of the program executes correctly e.g. for lots of interrupts you need the routine to finish quickly ready for the next one.

Hardware Interrupt or polling?

The benefit of the hardware interrupt is that processor time is used efficiently and not wasted polling input ports. The benefit of polling is that it is easy to do.

Another benefit of using interrupts is that in some processors you can use a wake-from-sleep interrupt. This lets the processor go into a low power mode, where only the interrupt hardware is active, which is useful if the system is running on batteries.


Hardware interrupt Common terms

Terms you might hear associated with hardware interrupts are ISR, interrupt mask, non maskable interrupt, an asynchronous event, and interrupt vector and context switching.

Setting up Hardware Interrupt in Microcontroller

avr interrupt cvavr

There are 3 external interrupts in Atmega 16. They are

  • INT0 : PD2, Pin 16
  • INT1 : PD3, Pin 17
  • INT2 : PB2, Pin 3

There are 3 modes of external Interrupts,

  • Low Level: In this mode interrupt occurs whenever it detects a ‘0’ logic at INT pin. To use this, you should put an external pull up resistance to avoid interrupt every time.

  • Falling Edge: In this mode interrupt occurs whenever it detects a falling edge that is ‘1’ to ‘0’ logic change at INT pin.

  • Rising Edge: In this mode interrupt occurs whenever it detects a falling edge that is ‘0’ to ‘1’ logic change at INT pin.

Functions of Interrupt Service Routine

After generating the code, you can see the following function,

// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
// Place your code here

}

You can place your code in the function, and the code will be executed whenever interrupt occurs.

UART

UART (Universal Asynchronous Receiver Transmitter)

It is a way of communication between the microcontroller and the computer system or another microcontroller. There are always two parts to any mode of communication-a Receiver and a Transmitter. Hence, our Atmega can receive data as well as send data to other microcontroller, computer or any other device.

UART: Theory of Operation

Figure 16 illustrates a basic UART data packet. While no data is being transmitted, logic 1 must be placed in the Tx line. A data packet is composed of 1 start bit, which is always a logic 0, followed by a programmable number of data bits (typically between 6 to 8), an optional parity bit, and a programmable number of stop bits (typically 1). The stop bit must always be logic 1.
Most UART uses 8bits for data, no parity and 1 stop bit. Thus, it takes 10 bits to transmit a byte of data.


avr uart


Figure 17: Basic UART packet format: 1 start bit, 8 data bits, 1 parity bit, 1 stop bit.

BAUD Rate: This parameter specifies the desired baud rate (bits per second) of the UART. Most typical standard baud rates are: 300, 1200, 2400, 9600, 19200, etc. However, any baud rate can be used. This parameter affects both the receiver and the transmitter. The default is 2400 (bauds).

In the UART protocol, the transmitter and the receiver do not share a clock signal. That is, a clock signal does not emanate from one UART transmitter to the other UART receiver. Due to this reason the protocol is said to be asynchronous.


Since no common clock is shared, a known data transfer rate (baud rate) must be agreed upon prior to data transmission. That is, the receiving UART needs to know the transmitting UART’s baud rate (and conversely the transmitter needs to know the receiver’s baud rate, if any). In almost all cases the receiving and transmitting baud rates are the same. The transmitter shifts out the data starting with the LSB first.
Once the baud rate has been established (prior to initial communication), both the transmitter and the receiver’s internal clock is set to the same frequency (though not the same phase). The receiver "synchronizes" its internal clock to that of the transmitter’s at the beginning of every data packet received. This allows the receiver to sample the data bit at the bit-cell center.

The receiver detects the start bit by detecting the transition from logic 1 to logic 0 (note that while the data line is idle, the logic level is high). In the case of 16450 UART, once the start-bit is detected, the next data bit’s "center" can be assured to be 24 ticks minus 2 (worse case synchronizer uncertainty) later. From then on, every next data bit center is 16 clock ticks later. Figure 2 illustrates this point.


Once the start bit is detected,the subsequent data bits are assembled in a de-serializer. Error condition maybe generated if the parity/stop bits are incorrect or missing.

avr uart

avr uart


Serial Port of Computer

We will be using Serial Port for communication between the uC and the computer. A serial port has 9 pins as shown. If you have a laptop, then most probably there won’t be a serial port. Then you can use a USB to serial Converter.

If you have to transmit one byte of data, the serial port will transmit 8 bits as one bit at a time. The advantage is that a serial port needs only one wire to transmit the 8 bits.

Pin 3 is the Transmit (TX) pin, pin 2 is the Receive (RX) pin and pin 5 is Ground pin. Other pins are used for controlling data communication in case of a modem. For the purpose of data transmission, only the pins 3 and 5 are required.

The standard used for serial communication is RS-232 (Recommended Standard 232). The RS-232 standard defines the voltage levels that correspond to logical one and logical zero levels. Valid signals are plus or minus 3 to 15 volts. The range near zero volts is not a valid RS-232 level; logic one is defined as a negative voltage, the signal condition is called marking, and has the functional significance of OFF. Logic zero is positive; the signal condition is spacing, and has the function ON.

Now we know that this is not the voltage level at which our microcontroller works. Hence, we need a device which can convert this voltage level to that of CMOS, i.e., logic 1 = +5V and logic 0 = 0V. This task is carried out by an IC MAX 232, which is always used with four 10uF capacitors.

The circuit is shown:
avr uart

The Rx and Tx shown in above figure (pins 11 and 12 of MAX232) are the Rx and Tx of Atmega 16 (PD0 and PD1 respectively).

Setting up UART in microcontroller

Once our electronic circuit is complete, we can start with coding. To enable UART mode in Atmega16, click on the USART tab in Code Wizard. Now depending upon your requirement, you can either check receiver, transmitter or both. You get a list of options to select from for the baud rate. Baud Rate is the unit of data transfer, defined as bits per second. We will select 9600 as it is fair enough for our purpose, and default setting in most of the applications (like Matlab, Docklight, etc.). Keep the communication parameters as default, i.e., 8 data, 1 stop and no parity and mode asynchronous. You also have option of enabling Rx and Tx Interrupt functions, but we won’t do at this point.

avr uart

Once you generate and save the code, all the register values are set by CVAVR and you only need to know some of the C functions to transfer data. Some of them are:

putchar()

To send one character to the buffer, which will be received by the device (uC or computer)?

E.g.,

putchar(‘A’); //sends character ‘A’ to the buffer
putchar(c); // sends a variable character c

getchar()

To receive one character from the buffer, which might have been sent by the other uC or the computer. E.g., if we have already defined a variable char c, then

c = getchar(); // receives the character from buffer and save it in variable c

putsf()

To send a constant string. Eg,

putsf(“Robocon Team IIT Kanpur”);


Docklight

To communicate with the computer, you need a terminal where you can send data through keyboard and the received data can be displayed on the screen. There are many softwares which provide such terminal, but we will be using Docklight. Its evaluation version is free for download on internet, which is sufficient for our purpose.

avr uart

To start with, check the Terminal Settings in Docklight. Go to Tools -> Project Settings. Select the Send/Receive communication channel, i.e., the name by which the serial port is known in your computer (like COM1…). In the COM port settings, select the same values as you had set while coding Atmega 16. So, we will select Baud Rate 9600, Data Bits 8, Stop Bits 1, Parity Bits none. You can select ‘none’ in Parity Error Character.

Click OK.

We are now ready to send/receive data, so, select Run -> Start Communication, or, press F5. If your uC is acting as a transmitter, then the characters it sends will appear in the Communication window of Docklight. E.g.,


putchar(‘K’);
delay_ms(500);
// Sends character K after every 500ms

Hence what you get on the screen is a KKKKKKKKKKKKKKKKKKKKKKKKK…….. one K increasing every 500ms. To stop receiving characters, select Run -> Stop Communication, or press F6.

If the receiver option is also enabled in Atmega16, then whatever you type from keyboard will be received by it. You can either display these received characters on an LCD, control motors depending on what characters you send, etc. e.g.,

c = getchar() ; // receive character
lcd_putchar(c); // display it on LCD
if (c==’A’)
PORTA=255; // if that character is A, make all pins of PORTA high.

When you are done with sending data, select Run -> Stop Communication, or press F6.

Implementing ADC (Most Important Core Concept)

Theory of Operation Of ADC (Core Concepts)

What we have seen till now that the input given to uC was digital, i.e., either +5 V (logic 1) or 0V (logic 0). But what if we have an analog input, i.e., value varies over a range, say 0V to +5V? Then we require a tool that converts this analog voltage to discrete values. Analog to Digital Converter (ADC) is such a tool.

adc avr

ADC is available at PORTA of Atmega16. Thus we have 8 pins available where we can apply analog voltage and get corresponding digital values. The ADC register is a 10 bit register, i.e., the digital value ranges from 0 to 1023. But we can also use only 8 bit out of it (0 to 255) as too much precision is not required.

Reference voltage is the voltage to which the ADC assigns the maximum value (255 in case of 8 bit and 1023 for 10 bit). Hence, the ADC of Atmega16 divides the input analog voltage range (0V to Reference Voltage) into 1024 or 256 equal parts, depending upon whether 10 bit or 8 bit ADC is used. For example, if the reference voltage is 5V and we use 10bit ADC, 0V has digital equivalent 0, +5V is digitally 1023 and 2.5V is approximately equal to 512.

ADC =Vin x 255/Vref (8 bit)

ADC =Vin x 1023/Vref (10 bit)


Setting up Microcontroller

To enable ADC in Atmega16, click on the ADC tab in Code Wizard and enable the checkbox. You can also check “use 8 bits” as that is sufficient for our purpose and 10 bit accuracy is not required. If the input voltage ranges from 0 to less than +5V, then apply that voltage at AREF (pin 32) and select the Volt. Ref. as AREF pin. But if it ranges from 0 to +5 V, you can select the Volt. Ref. as AVCC pin itself. Keep the clock at its default value of 125 kHz and select the Auto Trigger Source as Free Running. You can also enable an interrupt function if you require.

cvavr avr adc

Function for getting ADC value

Now when you generate and save the code, all the register values are set automatically along with a function:

unsigned char read_adc(unsigned char adc_input).

This function returns the digital value of analog input at that pin of PORTA whose number is passed as parameter, e.g., if you want to know the digital value of voltage applied at PA3, and then just call the function as,

read_adc(3);

If the ADC is 8 bit, it will return a value from 0 to 255. Most probably you will need to print it on LCD. So, the code would be somewhat like

int a; char c[10]; // declare in the section of global variables

a=read_adc(3);
itoa(a,c);
lcd_puts(c);

How does the timmer works-

Timers Basic Overview

Atmega 16 has following timers,

  • Timer 0, 8 bit
  • Timer 1, 16 bit consisting of two 8 bit parts, A and B
  • Timer 2, 8 bit

Now there are two clocks,

  • System Clock (fs): This is the clock frequency at which Atmega is running. By default it is 1 MHz which can be changed by setting fuse bits.

avr timers

  • Timer Clock (ft): This is the clock frequency at which timer module is running. Each timer module has different clocks.

Now ft can be in ratios of fs. That is, ft = fs, fs/8, fs/64 ...

For example, if we keep fs = 8 MHz then available options for ft are: 8 MHz, 1 MHz, 125 KHz ... (look in the image)

There are total 4 settings for Timers,

  • Clock Source: Source for timer clock, keep it as system clock. You can also provide external clock. Read datasheet for more information about external clock source.

  • Clock value: This is value of ft. Drop down for available options of ft. Chose whichever is required

  • Mode: There are many modes of timers. We will be discussing following 2 modes,

  • Fast PWM top = FFh
  • CTC top=OCRx (x=0, 1A, 2)

  • Output: Depending upon the mode we have chosen there are options for output pulse. We will look in detail later.

Basically each Timer has a counter unit with size 8 bit for Timer 0, 2 and 16 bit for Timer 1. I will be talking about Timer 0 and same will follow for other Timers.

Each counter has a register which increments by one on every rising edge of timer clock. After counting to its full capacity, 255 for 8 bit, it again starts from 0. By using this register we can have different modes.

  • Timer/Counter (TCNT0) and Output Compare Register (OCR0) are 8-bit registers.

  • TOP: The counter reaches the TOP when it becomes equal to the highest value in the count sequence. The TOP value can be assigned to be the fixed value 0xFF (MAX) or the value stored in the OCR0 Register. The assignment is dependent on the mode of operation.

Fast PWM Mode

avr timersPWM = Pulse Width Modulation.

This mode is used to generate pulse with

  • Fixed Frequency (F)
  • Variable Duty Cycle (D)

F = Ft / 256

D = OCR0 / 255 (non inverted output)

D = (255-OCR0) / 255 (inverted output)

By changing OCR0 value we can change the duty cycle of the output pulse.

As OCR0 is an 8bit register it can vary from 0 to 255.

0 ≤ OCR0 ≤ 255

Pins for Output pulse,

Timer 0 : OC0, pin 4
Timer 1A : OC1A, pin 19
Timer 1B : OC1B, pin 18
Timer 2 : OC2, pin 21

avr timers

avr timers

CTC Mode

CTC = Clear Timer on Compare Match.

This mode is to generate pulse with,

  • Fixed Duty Cycle (D = 0.5)
  • Variable Frequency (F)

F = ft / 2 (1+OCR0)

(corrected on 8th Feb, thanks to Ankur for pointing mistake)

D = 0.5

By changing value of OCR0 we can change the value of output pulse frequency. As OCR0 is an 8bit register it can vary from 0 to 255.

0 ≤ OCR0 ≤ 255

avr timers

LCD Interfacing

LCD Interfacing with AVR

Now we need to interface an LCD to our microcontroller so that we can display messages, outputs, etc. Sometimes using an LCD becomes almost inevitable for debugging and calibrating the sensors (discussed later). We will use the 16x2 LCD, which means it has two rows of 16 characters each. Hence in total we can display 32 characters.





Cell coordinates : (x,y)

0,0 1,0 2,0 3,0 4,0 5,0 6,0 7,0 8,0 9,0 10,0 11,0 12,0 13,0 14,0 15,0
0,1 1,1 2,1 3,1 4,1 5,1 6,1 7,1 8,1 9,1 10,1 11,1 12,1 13,1 14,1 15,1

avr cvavr lcd connections

Circuit Connection

There are 16 pins in an LCD; See reverse side of the LCD for the PIN configuration.
The connections have to be made as shown in image.


Settings in CVAVR

When we connect an LCD to Atmega16, one full PORT is dedicated to it, denoted by PORT-X in the figure. To enable LCD interfacing in the microcontroller, just click on the LCD tab in the Code Wizard and select the PORT at which you want to connect the LCD. We will select PORTC. Also select the number of characters per line in your LCD. This is 16 in our case. Code Wizard now shows you the complete list of connections which you will have to make in order to interface the LCD. These are nothing but the same as in the above figure for general PORT-X.

cvavr avr lcd


As you can see, there are some special connections other than those to uC, Vcc and gnd. These are general LCD settings. Pin 3 (VO) is for the LCD contrast, ground it through a <1kω>

Printing Functions

Now once the connections have been made, we are ready to display something on our screen. Displaying our name would be great to start with. Some of the general LCD functions which you must know are:

lcd_clear()

Clears the lcd. Remember! Call this function before the while(1) loop, otherwise you won’t be able to see anything!

lcd_gotoxy(x,y)

Place the cursor at coordinates (x,y) and start writing from there. The first coordinate is (0,0). Hence, x ranges from 0 to 15 and y from 0 to 1 in our LCD. Suppose you want to display something starting from the 5th character in second line, then the function would be

lcd_gotoxy(5,1);

lcd_putchar(char c)

To display a single character.

Ex,
lcd_putchar(‘H’);

lcd_putsf(constant string)

To display a constant string.

Ex,

lcd_putsf(“IIT Kanpur”);

lcd_puts(char_array)

To display a variable string, which is nothing but an array of characters (data type char) in C language. e.g., You have an array char c[10] which keeps on changing. Then to display it, the function would be called as

lcd_puts(c);

Now we have seen that only characters or strings (constant or variable) can be displayed on the LCD. But quite often we have to display values of numeric variables, which is not possible directly. Hence we need to first convert that numeric value to a string and then display it. For e.g., if we have a variable of type integer, say int k, and we need to display the value of k (which changes every now and then, 200 now and 250 after a second... and so on). For this, we use the C functions itoa() and ftoa(), but remember to include the header file stdlib.h to use these C functions.

itoa(int val, char arr[])

It stores the value of integer val in the character array arr. E.g., we have already defined

int i and char c[20], then

itoa(i,c);
lcd_puts(c);

Similarly we have

ftoa(float val, char decimal_places, char arr[])

It stores the value of floating variable f in the character array arr with the number of decimal places as specified by second parameter. E.g., we have already defined float f and char c[20], then

ftoa(f,4,c); // till 4 decimal places
lcd_puts(c);

Now we are ready to display anything we want on our LCD. Just try out something which you would like to see glowing on it ! I know you are going to print your name first :-)

I/O Ports Functioning

So lets start with understanding the functioning of AVR. We will first discuss about I/O Ports. Again I remind you that I will be using and writing about Atmega-16. Lets first have a look at the Pin configuration of Atmega-16. Image is attached, click to enlarge.

You can see it has 32 I/O (Input/Output) pins grouped as A,B,C & D with 8 pins in each group. This group is called as PORT.

  • PA0 - PA7 (PORTA)
  • PB0 - PB7 (PORTB)
  • PC0 - PC7 (PORTC)
  • PD0 - PD7 (PORTD)

Notice that all these pins have some function written in bracket. These are additonal function that pin can perform other than I/O. Some of them are.

  • ADC (ADC0 - ADC7 on PORTA)
  • UART (Rx,Tx on PORTD)
  • TIMERS (OC0 - OC2)
  • SPI (MISO, MOSI, SCK on PORTB)
  • External Interrupts (INT0 - INT2)

REGISTERS:

All the configurations in microcontroller is set through 8 bit (1 byte) locations in RAM (RAM is a bank of memory bytes) of the microcontroller called as Registers. All the functions are mapped to its locations in RAM and the value we set at that location that is at that Register, configures the functioning of microcontroller. There are total 32 x 8bit registers in Atmega-16. As Register size of this microcontroller is 8 bit, it called as 8 bit microcontroller.

All the information is given in the datasheet. Just open the datasheet of Atmega 16 and go to last lines in page 4 and start reading the Pin Descriptions. You will understand about functioning of each pin.

I/O PORTS:

Input Output functions are set by Three Registers for each PORT.

  • DDRX ----> Sets whether a pin is Input or Output of PORTX.
  • PORTX ---> Sets the Output Value of PORTX.
  • PINX -----> Reads the Value of PORTX.

Go to the page 50 in the datasheet or you can also see the I/O Ports tab in the Bookmarks.

DDRX (Data Direction Register)

First of all we need to set whether we want a pin to act as output or input. DDRX register sets this. Every bit corresponds to one pin of PORTX. Lets have a look on DDRA register.

Bit
7
6
5
4
3
2
1
0
PIN
PA7
PA6
PA5
PA4
PA3
PA2
PA1
PA0

Now to make a pin act as I/O we set its corresponding bit in its DDR register.

  • To make Input set bit 0
  • To make Output set bit 1

If I write DDRA = 0xFF (0x for Hexadecimal number system) that is setting all the bits of DDRA to be 1, will make all the pins of PORTA as Output.

Similarly by writing DDRD = 0x00 that is setting all the bits of DDRD to be 0, will make all the pins of PORTD as Input.

Now lets take another example. Consider I want to set the pins of PORTB as shown in table,

PORT-B
PB7
PB6
PB5
PB4
PB3
PB2
PB1
PB0
Function
Output
Output
Input
Output
Input
Input
Input
Output
DDRB
1
1
0
1
0
0
0
1

For this configuration we have to set DDRB as 11010001 which in hexadecimal is D1. So we will write DDRB=0xD1

Summary

  • DDRX -----> to set PORTX as input/output with a byte.
  • DDRX.y ---> to set yth pin of PORTX as input/output with a bit (works only with CVAVR).

PORTX (PORTX Data Register)

This register sets the value to the corresponding PORT. Now a pin can be Ouput or Input. So lets discuss both the cases.

1. Output Pin:

If a pin is set to be output, then by setting bit 1 we make output High that is +5V and by setting bit 0 we make output Low that is 0V.

Lets take an example. Consider I have set DDRA=0xFF, that is all the pins to be Output. Now I want to set Outputs as shown in table,

PORT-A
PA7
PA6
PA5
PA4
PA3
PA2
PA1
PA0
Value
High(+5V)
High(+5V)
Low(0V)
Low(0V)
Low(0V)
High(+5V)
High(+5V)
Low(0V)
PORTA
1
1
0
0
0
1
1
0

For this configuration we have to set PORTA as 11000110 which in hexadecimal is C6. So we will write PORTA=0xC6;

2. Input Pin:

If a pin is set to be input, then by setting its corresponding bit in PORTX register will make it as follows,

  • Set bit 0 ---> Tri-Stated
  • Set bit 1 ---> Pull Up

Tristated means the input will hang (no specific value) if no input voltage is specified on that pin. Pull Up means input will go to +5V if no input voltage is specified on that pin.

Summary

  • PORTX ----> to set value of PORTX with a byte.
  • PORTX.y --> to set value of yth pin of PORTX with a bit (works only with CVAVR).

PINX (Data Read Register)

This register is used to read the value of a PORT. If a pin is set as input then corresponding bit on PIN register is,

  • 0 for Low Input that is V <>
  • 1 for High Input that is V > 2.5V (Ideally, but actually 0.8 V - 2.8 V is error zone !)

For an example consider I have connected a sensor on PC4 and configured it as an input pin through DDR register. Now I want to read the value of PC4 whether it is Low or High. So I will just check 4th bit of PINC register.

We can only read bits of the PINX register, can never write on that as it is meant for reading the value of PORT.

Summary

  • PINX ----> Read complete value of PORTX as a byte.
  • PINX.y --> Read yth pin of PORTX as a bit (works only with CVAVR).

I hope you must have got basic idea about the functioning of I/O Ports. For detailed reading you can always refer to datasheet of Atmega.

Serial Programmer

Serial Programmer's Circuit (Hardware)

This is the easiest programmer circuit to make. You just have to get Serial Port connector and three 1K resistors and you are done ! Circuit Diagram is attached.

avr serial programmer hardware pony prog at prog

Now open the datasheet of Atmega you are using (I am using Atmega-16). Go to the pin configuration and find the following pins and connect the programmer. Programming is done through SPI (Serial Peripheral Interface) which involves MISO, MOSI and SCK pins. RESET is used to reset the chip. 0 volt on this pin will reset the chip and for normal running it should be pulled up to +5V.

avr atmega16 pin configuartion

  • MOSI (Master Out Slave In)
  • MISO (Master In Slave Out)
  • SCK (Serial Clock)
  • RESET
  • GND (Ground)

Now connect the power supplies that is Vcc and GND to the micro controller.

Vcc = +5V and GND = 0V

Do not forget to connect Reset to Vcc with a 1K/10K resistor for pulling up.

Thats it ! We are ready with the hardware :)

Software

As I told you there are two parts of a programmer, hardware and software. We built this hardware as it is very easy with just 3-4 components. Now we need software which support this hardware and can comminucate with micro controller using this circuit. There are 2 good softwares for Windows. They are,

Both of them support Serial as well as Parallel port, but I have always preferred serial port because it has only 9 pins, hence a smaller connector is required.

Now let us discuss about them.

At-Prog

I consider it as simplest programmer ever ! It was my first programmer. The circuit we discussed is actually based on this programmer. Download the folder from the website, unzip it. It has an executable file named at-prog.exe double click to execute it.

Go to PORT and select the address of serial port (by default COM1). Once you click that Serecon2 detected should appear in the Activility tab. That is the name of the programmer circuit.

Turn on the power supply and connect the circuit to the micro controller.

Click on Check, it should show OK in the Activity tab and device name (ATMEGA16) will automatically come in the tab below check option. This is the autodetect option of this programmer which autodetects the device name connected by its signature.

Now just open the device file from File--->Open and click on Write. It will write and verify the program. Done ! So simple isnt it ? :)

avr atprog programmeravr atprog programmer

Pony Prog

One of the most commonly used programmers on Windows. Download it from the website and install it. Now lets set it up for our hardware.

First select AVR micro and AVR-Auto (you can also specify device name, Atmega16) in the chip options (last two drop down tabs)

Go to the Setup---->Interface-Setup. Then do the settings as shown in the picture below. Then connect the circuit to the microcontroller, turn on the power supply. Now click on Probe. You should get Test OK message. If not, check your connections again.

avr pony prog

Now lets read the Microcontroller. Go to Command---->Read All. It should start reading the signature and the flash memory. You should get Read Successful message after that.

avr pony prog

avr pony prog

So we are done with the settings and testings. Everything is working fine :) Now just open the hex file from File---->Open-Device-File

Go to Command---->Write-Program(Flash). It will start writing and then veryfying the code. Congratulations :) you did it !

avr pony prog

Compilation Of code

Compiler / IDE (Integrated Development Enviornment)

An IDE has following functions:

  • Preprocessing
  • Compilation
  • Assembly
  • Linking
  • Object Translation
  • Text Editor

If we just use compiler and linker independently we still need to get a text editor. So combining everything will actually mess things up. So the best way is to get a Software which has it all. Thats called an Integrated Development Enviroment, in short IDE.

I consider Code-Vision-AVR to be the best IDE for getting started with AVR programming on Windows XP, Vista. It has a very good Code Wizard which generate codes automatically ! You need not mess with the assembly words. So in all my tutorials I will be using CVAVR. You can download evaluation version for free which has code size limitation but good enough for our purpose.

For all my examples I will be using Atmega-16 as default microcontroller because it very easily available and is powerful enough with sufficent number of pins and peripherals we use. You can have a look on the datasheet of Atmega-16 in the datasheet section.

Lets take a look on the software. The main window looks like following (click to enlarge the pic)

cvavr avr ide

cvavr avr ide

Now click on File ---> New --->Project

A pop up window will come asking whether you want to use Code Wizard AVR, obviously select yes because that is the reason we are using CVAVR !

Now have a look on this Wizard. It has many tabs where we can configure PORTS, TIMERS, LCD, ADC etc. I am explaining some of them

CHIP:

Select the chip for which you are going to write the program. Then select the frequnecy at which Chip is running. By default all chips are set on Internal Oscialltor of 1 Mhz so select 1 MHz if that is the case. If you want to change the running clock frequency of the chip then you have to change its fuse bits (I will talk more about this in fuse bits section).

cvavr avr ide

PORT:

PORT is usually a collection of 8 pins.

From this tab you can select which pin you want to configure as output and which as input. It basically writes the DDR and PORT register through this setting. Registers are basically RAM locationswhich configures various peripherals of microcontroller and by changing value of these registers we can change the function it isperforming. I will talk more about registers later. All the details are provided inthe datasheet.

So you can configure any pin as output or input by clicking the box.

For Atmega-16 which has 4 Ports we can see 4 tabs each corresponding to one Port. You can also set initial value of the Pins you want to assign. or if you are using a pin as input then whether you want to make it as pullup or tristated, again I will talk in details about these functions later.

Similarly using this code wizard you can very easily configure all the peripherals on the Atmega.

Now for generating code just go to File ---->Generate, Save and Exit (of the code wizard obviously !)

Now it will ask you name and location for saving three files. Two being project files and one being the .C file which is your program. try to keep same names of all three files to avoid confusion. By default these files are generated in C:\CVAVR\bin

The generated program will open in the text editor. Have a look it has some declarations like PORT, DDR, TCCR0 and many more. These are all registers which configures various functions of Atmega and by changing these value we make different functions. All the details about the registers are commented just below them. Now go down down and find following infinite while loop there. We can start writing our part of program just before the while loop. And as for most of the applications we want microcontroller to perform the same task forever we put our part of code in the infinite while loop provided by the code wizard !

while (1)
{
// Place your code here

};
}

See how friendly this code wizard is, all the work (configuring registers) automatically done and we dont even need to understand and go to the details about registers too !

Now we want to generate the hex file, so first compile the program. Either press F9 or go to Project--->Compile.

It will show compilation errors if any. If program is error free we can proceed to making of hex file. So either press Shift+F9 or go to Project---->Make. A pop up window will come with information about code size and flash usage etc.

So the machine file is ready now ! It is in the same folder where we saved those 3 files. Now we want to make a programmer and feed our code to the microcontroller (Atmega-16)

Overview

Features

  • Advanced RISC Architecture
  • Up to 16 MIPS Throughput at 16 MHz
  • 16K Bytes of In-System Self-Programmable Flash
  • 512 Bytes EEPROM
  • 1K Byte Internal SRAM
  • 32 Programmable I/O Lines
  • In-System Programming by On-chip Boot Program
  • 8-channel, 10-bit ADC
  • Two 8-bit Timer/Counters with Separate Prescalers and Compare Modes
  • One 16-bit Timer/Counter with Separate Prescaler, Compare Mode, and Capture
  • Four PWM Channels
  • Programmable Serial USART
  • Master/Slave SPI Serial Interface
  • Byte-oriented Two-wire Serial Interface
  • Programmable Watchdog Timer with Separate On-chip Oscillator
  • External and Internal Interrupt Sources

Pin Configuration

avr atmega16 pin configuartion

Pin Description

VCC: Digital supply voltage. (+5V)

GND: Ground. (0 V) Note there are 2 ground Pins.

Port A (PA7 - PA0)

Port A serves as the analog inputs to the A/D Converter. Port A also serves as an 8-bit bi-directional I/O port, if the A/D Converter is not used. When pins PA0 to PA7 are used as inputs and are externally pulled low, they will source current if the internal pull-up resistors are activated. The Port A pins are tri-stated when a reset condition becomes active, even if the clock is not running.

Port B (PB7 - PB0)

Port B is an 8-bit bi-directional I/O port with internal pull-up resistors (selected for each bit). Port B also serves the functions of various special features of the ATmega16 as listed on page 58 of datasheet.

Port C (PC7 - PC0)


Port C is an 8-bit bi-directional I/O port with internal pull-up resistors (selected for each bit). Port C also serves the functions of the JTAG interface and other special features of the ATmega16 as listed on page 61 of datasheet. If the JTAG interface is enabled, the pull-up resistors on pins PC5 (TDI), PC3 (TMS) and PC2 (TCK) will be activated even if a reset occurs.

Port D (PD7 - PD0)

Port D is an 8-bit bi-directional I/O port with internal pull-up resistors (selected for each bit). Port D also serves the functions of various special features of the ATmega16 as listed on page 63 of datasheet.

RESET: Reset Input. A low level on this pin for longer than the minimum pulse length will generate a reset, even if the clock is not running.

XTAL1: External oscillator pin 1

XTAL2: External oscillator pin 2

AVCC: AVCC is the supply voltage pin for Port A and the A/D Converter. It should be externally connected to VCC, even if the ADC is not used. If the ADC is used, it should be connected to VCC through a low-pass filter.

AREF: AREF is the analog reference pin for the A/D Converter.

Block Diagram

avr atmega16 block diagram

Introduction to Microcontrollers

Introduction to Micro controller

New to micro-controllers ? Wanna learn about it ? I was also in the same condition few years back ! (May 2006) Got some help from seniors and almighty Google then things got started.

So lets start from the very basic !

You must be knowing about Digital Integrated Circuits (ICs) right ? For example:

  • 7404: Hex Inverter
  • 7408: Quad 2-input AND gate
  • 7410: Triple 3-input NAND Gate
  • 7432: Quad 2-input OR Gate
  • 7457: 60:1 Frequency divider

There are AND, XOR, NAND, NOR, OR logic gate ICs, Counters, Timers, Seven Segment Display Drivers and much more. Just check out 7400 Series and 4000 Series of Integrated Circuits.

Now lets take Quad 2 input AND gate IC. It has 4 AND gates, each having 2 pins for input and 1 pin for output. The truth table or the function table of each gate is fixed. Which is as folllows:

Input 1
Input 2
Output
0
0
0
0
1
0
1
0
0
1
1
1

Similarly all the Integrated circuits have there function tables and input and output pins fixed. You can not change the function and no input pin act as output and vice versa. So whenever you want to design some circuit you first have to get the output as a function of inputs and then design it using gates or whatever the requirement is.

So once a circuit is built we can not change its function ! Even if u want to make some changes again you have to consider all the gates and components involved. Now if you are designing any circuit which involves change of the function table every now and then you are in trouble ! For example if I want to design an Autonomous Robot which should perform various tasks and I don’t just want to fix trhe task. Suppose I make it to move in a path then I want to change the path ! How to do that ?

Here comes the use of Microcontrollers ! Now if I give you an Integrated Circuit with 20 pins and tell you that you can make any pin as output or input also you can change the function table by programming the IC using your computer ! Then your reactions will be wow ! that’s nice :) That’s what the most basic function of a microcontroller is. It has set of pins called as PORT and you can make any pin either as output or input. After configuring pins you can program it to perform according to any function table you want. You can change the configuration or the function table as many times you want.

There are many Semiconductor Companies which manufactures microcontrollers.

Some of them are:atmega16 avr

  • Intel
  • Atmel
  • Microchip
  • Freescale
  • Motorola
  • ZiLOG

We will discuss about Atmel Microcontrollers commonly known as AVR in this section.

Question: How a microcontroller works !

Answer: Well I can not go into lot of details about the working because it is a vast topic in itself. I can just give an overview.

Microcontroller consists of an Microprocessor (CPU that is Central processing Unit) which is interfaced to RAM (Random Access Memory) and Flash Memory (one your pen drive has !). You feed your program in the Flash Memory on the microcontroller. Now when you turn on the microcontroller CPU access the instruction from RAM which access your code from Flash. It sets the configuration of pins and start performing according to your program. For details refer,

Question: How to make the code ?

Answer: You basically write the program on your computer in any of the high level languages like C, C++, JAVA etc. Then you compile the code to generate the machine file. Now you will ask what this machine file is ? All the machines understands only one language, 0 & 1 that is on and off. Now this 0 & 1 both corresponds to 2 different voltage levels for example 0 volt for 0 logic and +5 volt for 1 logic. Actually the code has to be written in this 0,1 language and then saved in the memory of the microcontroller. But this will be very difficult for us ! So we write the code in the language we understand (C) and then compile and make the machine file (.hex) After we make this machine file we feed this to the memory of the microcontroller.

Question: How to feed the code in the flash of Microcontroller ?

Answer: Assuming you have the machine file (.hex) ready and now you want to feed that to the flash of the microcontroller. Basically you want to make communication between your computer and microcontroller. Now computer has many communication ports such as Serial Port, Parallel Port and USB (Universal Serial Bus).

Lets take Serial Port, it has its own definition that is voltage level to define 0 & 1 (yeah all the data communication is a just collection of 0 & 1 ) Serial Port's protocol is called as UART (Universal Asynchronous Reciever & Transmitter) Its voltage levels are, -12 volt for 0 logic and +12 volt for 1 logic.

Now the voltage levels of our micrcontroller is based on CMOS (Complimentary Metal Oxide Semiconductor) technology which has 0 volt for 0 logic and +5 volt for 1 logic.

Two different machines with 2 different ways to define 0 & 1 and we want to exchange information between them. Consider microcontroller as a French and Computer's Serial Port as an Indian person (obviously no commom language in between !) If they want to exchange information they basically needs a mediator who knows both the language. He will listen one person and then translate to other person. Similarly we need a circuit which converts CMOS (microcontroller) to USART (serial port) and vice versa. This circuit is called as programmer. Using this circuit we can connect computer to the microcontroller and feed the machine file to the flash.

Compiler / IDE (Integrated Development Environment)

Atmel Microcontrollers are very famous as they are very easy to use. There are many development tools available for them. First of all we need an easy IDE for developing code. I suggest beginners to use CVAVR (Code Vision AVR) Evaluation version is available for free download from the website. It has limitaion of code size. It works on computers with Windows platform that is Windows XP & Vista.

Some famous compilers/development tools supporting Windows for Atmel Microcontrollers are:

AVRGCC is a very nice open source compiler used by most of the people.

Programmer

Programmer basically consists of two parts:

  • Software (to open .hex file on your computer)
  • Hardware (to connect microcontroller)

Hardware depends on the communication port you are using on the computer (Serial, Parallel or USB). I suggest beginners to use Serial Programmer as it is very easy to build. Software for that is Pony Prog or At-prog. Some famous Windows (XP, Vista) programmers are: