You may commonly encounter a term "Embedded System". Simply we can say, we use microcontrollers to build Embedded Systems. We will embed a MCU in a system which will perform our desired operation. Starting from digital watches and mp3 players up to traffic system controllers and Nuclear reactor controllers all are embedded systems. We already mentioned that the devices or the systems which require a computing brain can be implemented using microcontrollers.
The Steps to Build an Embedded System
Now we know the basics of a computer system. We can start designing our own embedded systems. The beauty of this work is that you can design
almost anything you want starting from a simple calculator up to your dream robot. Your creativity is the key to build a system.
What about a system that will monitor your room temperature and adjust the fans accordingly? It may be hard to think, but very soon you will discover that it is just a matter of few lines of code like this,
This is just an example of how a logic might be implemented. But you can certainly think here that you will need a temperature sensor to determine the temp, give this reading as the input to the uC, the uC then applies your code! But how? You have to program the MCU using these codes. The outputs of the MCU will be connected to the fan controls. You know what happens then.
The thing is not as simple as I say, not so tough either. The steps are given below,
|Figure: Embedded System Development Process|
Lets discuss the steps in brief. I will cover in detail in later chapters
Plan a System
First of all we have to make a plan of a particular system. The first question is what do we need to do? I am going to explain with examples.
There are many tasks that require some control mechanism. We might want to develop,
- A system which will monitor the water level of the rooftop water tank and run the pump motor as required.
- A clock which will count time and display it on some seven segment displays.
- A music player which will play our favorite tracks.
Input: These are mainly the sensors that should be connected to the uC. In these examples Water level sensor, clock adjustment buttons and play-pause-volume control buttons of the music player are the inputs. These are attached to the uC as the inputs so that it can decide what external condition has occurred and what should it do at that time.
Process: The microcontroller takes the inputs. Based on the input conditions, it determines its tasks as instructed in the program. It also performs any calculation as necessary. Then it produces the outputs accordingly.
Output: In these examples the outputs are the motor main switch or relay, seven segment displays and loudspeakers/headphones. The outputs are determined either by the inputs or the state of the program in the uC.
- The outputs may not be the direct functions of the inputs. For example, in the clock, the inputs are the adjustment buttons only. The output comes from the clock count value in the memory.
- The inputs alone may not determine the system operation. There may be other sources of information. For example, data stored in the memory or some internal variables that is programmed to determine a situation. For example, the music player will play audio tracks from the memory.
Plan the Algorithms
In this stage we will prepare the algorithm of the desired system behavior. We will do this for the Automatic Water Pump Controller example only. The algorithm written here is just to give you an idea. Actual system and operation may differ.
1. Read water level.
2. If water level < minimum level AND motor = off, then motor = on.
3. If motor = on AND water level > maximum, then motor =off.
4. Return to 1.
Very simple, right? The microcontroller operates in an infinite loop. It starts at 1, goes through 2, 3 and 4. It returns to 1 and repeats the whole process again. So the system continuously checks the water level and runs the motor when required. It also stops the motor after the water is filled up.
Write the codes in an IDE
We will write the codes in C. We need an IDE (Integrated Development Environment) to write our codes and a compiler to compile them. As we are going to use AVR microcontrollers, both of them must support AVRs. These two come in separate packages and can be downloaded and used free of charge.
|Screenshot: AVR Studio 4.12|
- We will use WinAVR 20060421, a package that contains the GNU GCC compiler for C and C++.
We will write our program code in the IDE and the compiler will compile the code and produce output in a usable format for the uC.For the water tank example I have written the codes shown below. Click the image and open it in a new window for better view. Read the comments in green. I have described the codes in detail below.
|Figure: Example code for Automatic Water Pump Controller|
I have not introduced to some features yet. So the code may be little hard to get. I will cover the AVR architecture in the next chapter. For now just keep in mind that, There are ports on a uC chip which can act as inputs or outputs. In the atmega8 uC, there are three ports named PORT B, PORT C and PORT D. Here we have used PORT B as input and PORT C as output.
We assume to install some sensor device in the tank that could measure the water level and produce digital output to feed PORT B. We have connected the motor main switch to be driven by PORT C. That should be enough for now.
- In the beginning, just like C programs, we included a header file. The functions we used in the code can be found in the basic input output header file named io.h in the "avr/.." directory.
- Then we defined two constants as minlevel and maxlevel containing the two specified water levels in binary values.
- Then we have written the main() function. This is the main routine that the uC will follow.
- We must specify which ports are inputs and which are outputs. In the beginning we have initialized two registers DDRC and DDRB. DDRC is set to a value such that PORT C will act as output and DDRB is set to a value such that PORT B act as input. DDRB and DDRC are two registers that define the modes of PORT B and PORT C operation respectively.
- After configuring the ports, we defined a variable just to extract the value from PORT B which is connected to the water level sensor. The variable could also be defined as integer or unsigned integer.
- The next task is important; we have created an endless loop. We used for(;;) loop here, but we can also use while(1) as an infinite loop. We have kept the condition checking field and the neighboring fields in the for loop blank, so that it never ends.
- In the block of code inside the loop the uC reads the water level from PORT B, then checks whether it is required to run or stop the motor. The motor is turned on by setting PORTC =0xFF (HIGH) and turned off by setting PORTC = 0x00 (LOW).
You might ask one question, why do we need an endless loop? It is required, because we want our uC to run endlessly until we turn it off. Whenever we power up the uC, it will initialize itself once and keep doing the things described in the code block of the infinite loop endlessly.
The numbers are normally represented in decimal. We will commonly use binary and hexadecimal representation in our codea for convenience. Here is how to represent 255 in binary and hex.
0b11111111 255 in binary
0xFF 255 in hexadecimal
Sometimes it is better to use binary and sometimes it is better to use hex. You will understand it soon.
Compile & Simulate
After we have completed writing code in AVR Studio, we will save the code in example.c file. The compiler will compile the code and produce low level machine language. We will get a example.hex file after compilation. The *.hex files will be used to program the AVR.
Simulation is optional. We can see what happens with the AVR when it executes our program by simulating the code instantly after compilation in AVR Studio. This is very useful for finding code errors quickly. I will demonstrate it later when needed.
Transferring the code to uC (Programming the Device)
We will transfer the program to our uC flash memory. From the memory the CPU will run the program. Our microcontroller has a built in flash memory to store the program. We need a “Data Cable” that will connect our PC to the MCU and let us transfer the program. We also need a software that will do that task. This is how we will program our microcontroller.
There are various programmers found in the world market for programming the uC. In our country it is rare. So we have to make one ourselves. The AVRs support In System Programming (ISP). I will show how to make an ISP cable later. It’s very easy to make.
There is a program to make our job easier. It is called Pony Prog. It is also free to download. I will provide links later. It takes our *.hex files and programs our AVRs in just a click.
|Screenshot: PonyProg main window|
Running and testing the system
We will implement our system primarily in the prototype boards or breadboards. We will check everything for any mistakes in the program or the system design. If we identify any mistake we will correct them accordingly. Flash memory is used as the program memory of the uC, so we can program it a million times! We can easily modify our code and reprogram it.
At the final level we will implement our system in PCB (Printed Circuit Board). The PCB design process is now very simple as very good design software packages are available. I will try to cover a chapter on designing PCBs later. For now, breadboard implementation would be enough.
I have just given a brief introduction to the steps in this chapter. I will describe every process broadly when I start developing some tutorial projects.