Sisujuht

/home/www/roboticlab/homelab_data/pages/en/start|Introduction.txt— MISSING PAGE — /home/www/roboticlab/homelab_data/pages/en/preface|Preface.txt— MISSING PAGE —

Guidelines

This guideline demonstrates how to use this site and Robotic HomeLab kit..

This site is dedicated to the Practical Robotics and Microcontroller theory and practice including practical toolkit: Robotic HomeLab.

When using Robotic HomeLab kits, first owner should register himself in this site and claim supervisor rights.

The site has several sections (menu on the left) which are intended to use directly on the teaching process. Following schematics describes which section (top division) is applied in sequence when introducing new topics to students.

Additional material can be found in following links:

Robotic HomeLab II

Robotic HomeLab owner has 3 month free access to DistanceLab environment Robotic HomeLab II testbed. Claim your permissions from lab owner. See video how it works.

See more about:

Authors

The most content of this page is created by the developers of Robotic HomeLab solution. Copyright: Raivo Sell and Mikk Leini if not noted otherwise.

RAIVO SELL Tallinn University of Technology, senior researcher, Ph.D. Department of Mechatronics raivo.sell@ttu.ee

MIKK LEINI TUT Robotics Club NPO, member of the board

Other authors

SVEN SEILER - AVR-CAN section

PEETER SALONG Stoneridge Electronics, software engineer. - Linux installation for KontrollerLab, LDR theory

ÜLLAR SOON - Exercise solutions for beginners

TARMO KOPLE - Linux repository and automated installation on Ubuntu

RAIN ELLERMAA

HEIKO PIKNER

Feedback

Please provide feedback if you have used or tested Robotic HomeLab kit.

Online survey

Frequently Asked Questions

Microcontrollers and Robotics

Microcontrollers

First microcontroller in the world: Intel 8048

A microcontroller is basically a computer which is placed on a single integrated circuit chip. It consists of memory, a processor, as well as input-output interfaces. Microcontrollers are programmed to run a certain task, which means, if there is a need to change or enhance its functionality, one must install a new program on the chip. Features that differentiate microcontrollers from other computers (PC, laptop, server, etc.) are:

  • All functions are placed on a single chip in a smaller and more compact scale.
  • It is programmed to perform a certain task; in order to change its functionality new software must be installed.
  • It consumes less power because all physical characteristics are smaller and less energy demanding than in a PC, laptop or server. Developers of microcontrollers concentrate on low energy demand so that mobile applications that use batteries can work longer.
  • Single purpose inputs and outputs. Microcontrollers have so called peripherals, which establish connections between a microcontroller and other microcontrollers or computers (e.g. USB, CAN, UART), help to understand the processes in the real physical world (e.g. switching actions, temperature measuring, etc. ) and help control conditions (e.g. control motor, trigger alert, etc.)

Microcontrollers can be found in a variety of everyday items: household appliances (e.g. microwave ovens, TV-sets), toys (Lego NXT, talking dolls), vehicles (cars, hoists), etc. Microcontrollers’ wide usage has been possible because they are easy to program and have a wide range of functionalities; hence, it is very easy to add new features and upgrade the level of intelligence of the appliance they are in.

Robotics

Robotics is a science that combines the technology and knowledge necessary to build robots. Due to the fast development of technology, the term robot, as an automatic machine that replaces humans, is not so clearly defined anymore. A robot is no longer just a humanoid robot, robotic hand at an auto assembly line, autopilot in aircraft, artificial intelligence built of living neurons or simple cleaning robot; it is also computer software that completes tasks meant for humans (for example, compiles reports). It is known that robots are built to replace humans at certain tasks. There are many reasons for this: dangerous working conditions, cheaper production, monotonous work may cause humans to err, new systems are so complex and time-critical, that automatic systems can make better decisions than humans.

Microcontrollers in Robotics

Because of the breadth of robotics, we define it as hobby robotics; these systems are not too complex, and it is possible to build them by oneself. Common microcontrollers in hobby robotics are:

  • Atmel AVR microcontrollers (ATmega, ATtiny, etc.)
  • Microchip Technology PIC microcontrollers (PIC16, PIC24, etc.)
  • Microcontrollers based on ARM technology.

Quite often third parties have created development boards and environments based on microcontrollers mentioned herein before. For example: Arduino (AVR), BASIC Stamp (PIC) and Lego NXT (ARM). The necessities for developing HomeLab that are described in this book are based on the AVR ATmega128 microcontroller. A question arises from the large amount of microcontrollers and development boards available: how to find the most appropriate? Generally we can classify the following four properties: - price, physical characteristics, development environment and customer support. Notable physical characteristics are:

  • processor operating frequency - determines chip operating speed
  • program memory capacity – determines the size of the program that can be installed on the chip
  • data memory capacity – how much data can be processed in the program
  • number of input/output pins and their function – different pins have different possibilities
  • number of timers – important for application timing criteria
  • energy consumption – important for mobile applications

Here the development environment is PC software, which allows creating and compiling programs, uploading programs to the microcontrollers and bridging in the programs during running in order to detect possible faults. How easy and comfortable it is to do all that becomes decisive because during the development phase of the program it will be the primary working area. All this leads to the fourth characteristic, which is customer support. It is important that receiving help and support for solving possible issues is made as easy as possible. By considering all four mentioned properties, it should be possible to find the development board needed.

Electronics

Some electronic circuits in practical examples are so common that they are separately described in the following chapters. It's important to learn them as they simplify the understanding of the examples, and will most probably help in building your own circuits too.

Ohm's Law

Ohm's law states that the current through a conductor between two points is directly proportional to the potential difference or voltage across the two points, and inversely proportional to the resistance between them, provided that the temperature remains constant.

The equation is as follows:

Resistance of the conductor, applied voltage and current through the resistance

I = U / R

where:

  • I is current
  • U is voltage
  • R is resistance

Several other equations that are used often in electronics are derived from Ohm's law.

LED Resistor Calculation

If the supply voltage is higher than the LED's voltage, the resistor has to be included in the circuit in series. The resistor limits the current and produces the required voltage drop. To find the correct value for the resistor, the following equation is derived from Ohm's law:

LED with series resistor

R = (Uin - Uf) / If
Ur = Uin - Uf
Pr = Ur ⋅ If

where:

  • R is resistance.
  • Uin is supply voltage.
  • Uf is LED voltage.
  • If is LED current.
  • Ur is voltage drop on the resistor.
  • Pr is power of the resistor that is transformed into heat.

The current limiting resistor of an LED has to be not smaller than R, and at least with the power of Pr.

Voltage Divider

A voltage divider is an electrical circuit which divides the input voltage. The output voltage is a portion of the input voltage and the value of the output is dependent on the resistor ratio in the circuit. The schematics on the right includes two resistors.

The output of the circuit is calculated by the following equation:

Electrical schematics of the voltage divider

U2 = U1 ⋅ (R2 / (R1 + R2))

where:

  • U1 is input voltage
  • U2 is output voltage
  • R1 and R2 are resistors

The equation is derived from Ohm's law

where:

I = U1 / (R1 + R2)

and:

U2 = I ⋅ R2

A voltage divider is very often used together with resistive sensors (photo resistor, thermistor etc.) where one of the resistors is replaced by the resistive sensor. In this way, the change of the resistance of the sensor is easily transformed to the voltage change, which is compatible with the microcontroller's analogous input.

Software development

The most popular PC programming language C is widely used also in programming microcontrollers. C is relatively straightforward to provide language constructs that map efficiently to machine instructions. In C-language, there are minimal number of keywords but it includes many characters with different meanings that makes learning more difficult. Correct way to develop software is to model it first. For modelling purpose simple algorithms can be created. Easiest way to represent an algorithm is to use flowchart graphical representation. The next chapter gives a short overview of drawing flowcharts as a model of program and C-language syntax which is also used in practical examples. The beginners are recommended to read additional guides.

Algorithms and flowchart

The algorithm is a step-by-step instruction, guideline or rule to perform some action or reach the solution for given problem. Flowchart is one of the way to represent algorithm graphically, where graphical elements like boxes, squares, circles, and arrows connecting them represent flow of control. Every element can represent on step in the instructions.

Simplified flowchart elements:

Start

Circle.

End

Filled circle inside bigger circle.

Action or expression

Rectangle. Inside rectangle a name of the action, name of the sub-routine or short description can be written. Similar actions can be included into one general action.

Sequence

Arrow, by pointing next activity.

Condition / Decision

Diamond (rhombus). Inside diamond is a logical expression and in most cases two arrows are drawn out from diamond. One is when logical expression results True (Yes/1) and other when expression result is False (No/0). Always both arrows have to be labeled. In special case only one arrow can be used as output from diamond. The case is when logical expression can clearly result only one solution, e.g. True. This is the case where for example endless cycle is used in program code (e.g. while (true)).

 

Data exchange

Trapezoid. Inside trapezoid a name or activity is described. In robotics it is usually used to communicate with sensors and user. For simplification also normal rectangle action can be used instead of trapezoid.

Examples

Drawing flowchart diagrams one can use common office suits like MS Word or MS Excel or OpenOffice/LibreOffice Writer or Calc but better results can be get by using special programs like MS Vision, OpenOffice/LibreOffice Draw, Google draw or some special diagram creating software.

Flowcharts describing microcontroller software usually do not have ends, instead whole main activity in an endless cycle. The exit condition of the endless cycle will never be true and therefore this is the case where condition block (diamond) can be represented only on exiting arrow. Condition it self can be notes simply True or 1. Creating diagrams it is important to keep in eye on the fact that if the program has forks, it can be done only through the diamond object. Junctions (two arrows are joining) can be described by special symbol, but in simple cases, one may simply have an arrow point to another arrow instead.

 
Following examples illustrate the use of flowchart elements for describing simple algorithm. First example is simple routine by describing one way flow without any cycle or decision points.

 
Following example describes a system which detects 1 m area and if an object entering into inspected area an alarm is triggered for a 10 seconds. Alarm is working until the object is left from the inspected area.

C Crash course

Program structure

As a principle, program written in C-language can be in any form, even in one line, because the compiler assumes only the following of syntax rules. However, it is advisable to take care of program coding style for clearness and simplicity. Typical structure of a C-language program: #include #include #define PI 3.141 typedef struct {

int a, b;

} element; element e; int main(void) {

// Local variables
int x;
// Program code
printf("Tere maailm!\n");

}

Comments

Programmer can write random text into program code for notes and explanations that is no compiled. Comments can also be used for temporally excluding some parts of code from compiling. Examples of two commenting methods:

Line comment is on one line. Text after two slash signs is considered as comment.

Data

Data types

C-language basic data types:

Type Minimum Maximum Bits Bytes
(signed) char -128 127 8 1
unsigned char 0 255 8 1
(signed) short -32768 32767 16 2
unsigned short 0 65535 16 2
(signed) long -2147483648 2147483647 32 4
unsigned long 0 4294967295 32 4
float -3.438 3.438 32 4
double -1.7308 1.7308 64 8

The word „signed“ in brackets is not necessary to use because data types are bipolar by default.

AVR microcontroller has int = short
PC has int = long

There is no special string data type in C-language. Instead char type arrays (will be covered later) and ASCII alphabet is used where every char has its own queue number.

Variables

Program can use defined type of memory slots - variables. Variable names can include latin aplhabet characters, numbers and underdashes. Beginning with a number is not allowed. When declarations to variables are being made, data type is written in front of it. Value is given to variable by using equal sign (=). Example about using variables:

char type variable c declaration char c; Value is given to variable c. c = 65; c = 'A'; A has in ASCII character map also value 65 int type variable i20 declaration and initialization int i20 = 55;

Declaration of several unsigned short type variables unsigned short x, y, test_variable; === Constants === Constants are declarated in the same way as variables, exept const keyword is added in front of data type. Constants are not changeable during program work. Example about using them: int type constant declaration const int x_factor = 100;

Structures

Basic data types can be arranged into structures by using struct keyword. Structure is a combined data type. Type is declarated with typedef keyword. Example about structures by creating and using data type:

Declaration of a new data type „point“ typedef struct { x and y coordinates and color code

int x, y;
char color;

} point;

declaration of a variable as data type of point point p; Assigning values for point variable p.x = 3; p.y = 14;

Arrays

Data types can be arranged into arrays. Array can have more than one dimensions (table, cube etc). Example about using one- and two-dimensional arrays:

Declaration of one- and two-dimensional arrays char text[3]; int table[10][10]; Creating a string from char array text[0] = 'H'; Char text[1] = 'i'; Char text[2] = 0; Text terminator (0 B) Assigning new value for one element. table[4][3] = 1;

 

Operations

Variables, constants and value returning functions can be used for composing operations. The result of and operation can be assigned to a variable, it can be used as a function parameter and in different control structures.

Arithmetic operators

C-language supported artithmetic operations are addition (+), subtraction (-), multiplication (*), division (/) and modulo (%). Some examples about using operators:

int x, y;

Modulo, multiplication and assigning value x gets value of 9 x = (13 % 5) * 3;

Adding-assigning operator x gets value of 14 x += 5;

Quick style method for subtracting 1 x gets value of 13 x–;

Logical operators

Logical operators are negation NOT (!), logic multiplication AND (&&) and logic addition OR (||). Example about using them:

bool a, b, c;

Initialization a = true; b = false; Negation c will get a value of false because a is true c = !a; Logic multiplication c will get a value of false because one of the operators is false c = a && b; Logic addition c will get a value of true because one of the operators is true c = a || b; NB! bool data type in C-language is actually missing and instead integers are used where 0 marks false and every other value marks true. For example, in HomeLab library bool is defined as unsigned char. Constant true marks a value of 1 and false a value of 0. === Relational and equality operators === Logical values are a result of comparison of variable values. Equality operators are equal to (==), not equal to (!=), greater than (>), greater than or equal to (>=), less than ( 15) && (y < 4); === Bit operations === Bit operations are for data manipulation in binary numeral system. These can be applied only to integer type data. Bit operations are quite similar to logic operations but differ from them because operation is carried out with every single bit not the whole number. Bit operations in C-language are inversion (~), conjunction (&), disjunction (|), antivalency (^), left shift (). Declaration of unsigned 8 bit char type variable Variable value is 5 in decimal system, 101 in binary system unsigned char c = 5; Disjunction of c with a digit 2 (010 in binary) c value will become 7 (111 in binary) c = c | 2; Bit left shift by 2 c value will become 28 (11100 in binary) c = c 2) x = 5; If x equals 5 and y equals 3 then the following code will be executed if [1] {

// Random action
y = 4;
my_function();

}

If statement can be longer and include code which will be executed in case the statement is false. For this, after if statement, else statement can be used. Example:

Is x equal with 5 ? if (x == 5) { Random action

z = 3;

} If this is false then x might be equal with 6 else if (x == 6) { Random action

q = 3;

} If x was not 5 nor 6 … else { Random action

y = 0;

}

 

Switch statement

When required to compare operations and variables with many different values, it is reasonable to use comparison statement with switch keyword. Example about using this:

int y;

Switch statement for comparing y switch (y) { is y equal to 1 ?

case 1:
	// Random action
	function1();
	break;
// is y equal to 2 ?
case 2:
	// Random action
	function2();
	break;
// All other cases
default:
	// Random action
	functionX();
	// break operation not needed,
	// because the comparison ends anyway

}

Loops

Loops can be used for executing code several times.

while loop

Code marked with while keyword is executed until condition in brackets is true. Example:

int x = 0;

Loop will execute until x is smaller than 5 while (x < 5) { x incrementation

x++;

}

 

for loop

for keyword loop is similar to while loop exept there are described operation executed before the loop and operation executed in the end of every loop cycle. Example:

int i, x = 0;

i is equal to 1 at the beginning of the loop. Loop will be executed until i is smaller than 5. i will be incremented in the end of every loop cycle. for (i = 0; i < 5; i++) { x addition by 2

x += 2;

}

here x value is 10 === Halting loops === As and exception exit from while and for loops can be made with keyword break. To start the next loop cycle without executing the remaining code in loop, continue keyword can be used. For example: int x = 0, y = 0; Infinite loop because 1 is logic true while (1) {

// Exit the the loop cycle if x becomes 100
if (x >= 100) break;

// x incrementation to end loop at some time
x++;

If x is 10 or less then the next cycle is started if (x /home/www/roboticlab/homelab_data/pages/en/programming/algorithm_code.txt— MISSING PAGE — ====== AVR microcontroller ====== The following chapters introduce the AVR microcontroller, which this book is based on. In spite of being so small, a microcontroller is full of features that have been documented by Atmel in a manual almost 400 pages long. Besides that, there are a lot of additional specific documents. All that information has been compressed to a fast and simple overview of the subject, which helps a beginner to understand better the AVR and learn to read its datasheet. ===== Introduction ===== [ATmega128 in SMT package (TQFP64, to be precise)] AVR is a series of 8-bit RISC microcontrollers produced by Atmel. AVR follows Harcard architecture and therefore has separate program and data memory. For the program it has an internally overwriteable flash memory, for data there are static (SRAM) and EEPROM memory. Controller's frequency is usually up to 16 MHz and performance is almost 1 MIPS per 1-megahertz cycle. The production of AVR microcontrollers began in 1997 and by now AVR is one of the most popular controllers with hobby electronics engineers. Thanks to cheap developing tools, the diversity of peripherals in a single package and low power consumption the initial success was gained. Today, there is another reason for choosing AVR: the massive amount of information and tutorials built up over the years. The AVR technology is inevitably aging, but to stay in competition Atmel is also making new AVR microcontrollers with more up-to-date peripherals and 16- and 32-bit buses, first of which are from the 8-bit compatible XMega series and the latter from the brand new AVR32 series. Based on the type of the application, there are several types of AVR microcontrollers, each with a different configuration. Most of the AVRs belong to the megaAVR series, which have a large program memory. To balance off the megaAVR series, there is also the tinyAVR series, which have smaller packages and less features. In addition to these, there are also different series of microcontrollers designed specifically for controlling USB, CAN, LCD, ZigBee, automatics, lighting and battery-powered devices. The following text describes the main features of megaAVR series microcontrollers, using one of the most popular controllers in this series, ATmega128, as an example. This controller is also in the HomeLab kit. Generally, all the AVR series microcontrollers' register names, meanings and usage is organized in a way to enable the examples also to be used with other controllers by making only slight changes. The main differences are in the peripherals. The code samples of this introduction are written in assembler and C, using AVR LibC. ==== Physical Appearance ==== [ATmega32 in 40-pin DIP casing] Like all other controllers, the AVR is also packaged in some standard shell. The traditional casing is DIP (also called DIL). DIP is a so-called casing on legs - all the pins extrude as legs, about 5 mm in length, from the black plastic casing. DIP casing is a sensible choice for hobby applications and prototypes, because there are cheap sockets available for it, so the microcontroller can easily be replaced, should it happen to malfunction or die. The legs are also a disadvantage of the DIP casing, because it requires holes to be drilled in the circuit board. The surface mount casings (SMT, also called SMD) are much more compact, because their pins are designed to be soldered straight to the board without the need to penetrate it. SMT microchips are in thin, coin-sized rectangular casings with pins about 1 mm long. A more precise hand and better tools are required for soldering SMT chips. AVRs are available in both DIP and SMT casings. The layout of the pins is designed as logically and electrically even as possible. For example, on larger chips, the ground and supply pins are located on several sides of the microcontroller, the pins for an external oscillator are near the ground pin, the bus pins are in numerical order, the communication pins are next to each other etc. AVRs digital pins are compatible with TTL/CMOS standard voltage levels. At 5 V supply voltage, 0 to 1 V means logical zero, which is also called zero, null, 0, low, ground, or GND. At the same supply voltage, 3 to 5.5 V means logical one, also called one, 1, high. This type of wide voltage range only applies to the inputs - the output voltage on a pin with no load is still 0 V or near supply voltage, depending on the state of the pin. The allowed analog voltage level on the ADC channels is 0 to 5.5 V. === ATmega128 === To better understand the following examples on ATmega128, there is a pinout schematic of ATmega128 (SMT package) below. Next to each pin, is a text with its number, primary function and secondary (alternate) function in brackets. Supply pins are GND and VCC. AVCC and AREF are analog-to-digital converter's supply and reference voltage pins. XTAL1 and XTAL2 are for connecting an external crystal oscillator, resonator or clock generator. Pins PB0 to PG4 mark the bits of input-output buses. The secondary functions of pins are discussed in the corresponding chapters. [ATmega128 pinout] ===== Registers ===== One of the toughest things for beginners to understand in a microcontroller is typically a register. When dealing with microcontrollers, it is impossible to get by without knowing what this device is. This book is in no way different, as the reader is also expected to familiarize him/herself with the concept of a register and therefore the following text will try to explain it in simple enough terms so that even a beginner can grasp the idea of a register. ==== Essence ==== [Tape player's buttons] A register is like a panel of buttons on a home appliance. It has switches, which can be turned on or off. One of the best examples is a simple tape player. For those, who don't remember, the tape player has (had) 6 buttons, left to right: * Record * Rewind * Play * Fast forward * Stop * Pause Each button does something, but only when it is used correctly. For example, the stop button does nothing unless a tape is playing - only then will it do something visible and stop the playback. Forward and rewind buttons, on the other hand, can be pressed at any time, because the tape can be wound in both directions, no matter if it is playing or stopped. The recording begins only when the play and record buttons are pressed down simultaneously. Some may have tried to press down several or all buttons at once - in this case, the tape player might have done something unexpected or break altogether. Microcontroller registers behave like buttons on a tape player - each button does something, when used correctly. By pressing the wrong buttons, a microcontroller usually won't break, but it won't work either. In reality, there are no buttons in the registers, instead there are a whole lot of transistors, which turn the electricity on and off. Simpler microcontrollers have 8 transistor-based switches in a single register. A register can be thought of as an 8-bit number, where every bit is marked by the state of one of those switches. For example, a bit value of 1 can mean that the switch is on and 0 that the switch is off. [Register's "buttons" and bit values] Since the state of a register's switches can easily be displayed as a number, a register can be compared to a memory, which can hold data in the size of one number. By this comparison, we see that registers actually are memory slots. The difference between a register and a memory slot is that a memory slot only stores the information, but in a register this information actually controls something. For example, if a binary value of 01100001 is written to a register, then three imaginary buttons are pressed down and something happens. On a tape player it is possible to press each button separately, but in a register it is more difficult to change the value of one „switch“ or bit. Typically it is necessary to change the entire content of the register. Before moving on to bit changing, one should know that there are a lot of registers in a microcontroller. Some parts of the microcontroller use tens of registers to control them. The variety of registers means that there has to be a way to distinguish between different registers and that is done by naming the registers. One register, for example, is called PORTB. Actually, these names are just to make things easier for the developer and each name corresponds to a numeric address. ==== Usage ==== To write to a register or read a value from it, it has to be addressed as a variable in C. The following example demonstrates writing a binary value to an imaginary register REG and then reading it to variable reg. Binary values are distinguished by 0b (leading zero), so that the compiler understands the numeric system. REG = 0b01100001; unsigned char reg = REG; There is nothing difficult in writing and reading register values, but it gets a little tricky if only a single bit needs to be changed. To change bits, one needs to know how to do binary math and use different numeric systems. It isn't forbidden to deal only with binary numbers, but they can be a bit troublesome, because binary numbers are quite long, and this is why most people use shorter hexadecimal numbers. [Hexadecimal numbers] In hexadecimal, the numbers are not only 0 and 1 as in binary, or 0 to 9 as in decimal, but instead 0 to F. A hexadecimal number consists of four bits. The table on the right shows the binary numbers and their hexadecimal counterparts. Binary numbers are converted to hexadecimal by reading bits four at a time, starting from the lowest rank. Ranks are read from right to left and their numbers start from 0. For example, the lowest ranked (rank 0) bit is 0 and the highest (rank 3) is 1. In the previous example, the register's binary value is 01100001, which is 61 in hexadecimal and is written as 0x61 (leading zero) in C. To change single bits in a number (register, variable or anywhere else for that matter) it is necessary to use binary operations. Binary operation is an operation between two binary numbers, where each bit of the numbers is subject to its own logical operation. Typically a microcontroller supports four binary operations, each having several names. The following section describes the logical operation behind each of these four binary operations with a single bit or multiple bits. [Negation, logical multiplication, logical addition and exclusive disjunction ]

 
* Negation / Inversion
Negation changes the bit's value to its opposite, a 0 becomes a 1 and vice versa. In C, negation is marked with „~“. * Logical multiplication / Conjunction
When multiplying two bits, the answer is 1 if both bits are 1 and in any other case 0. In C, logical multiplication is marked with „&“. * Logical addition / Disjunction
When adding two bits, the answer is 1 if at least one of the bits is 1 and 0 if both bits are 0. In C, logical addition is marked with „|“. * Exclusive disjunction / Exclusive OR / XOR
Exclusive OR operation will return 1 if the two bits differ from each other (one is 1 and the other 0), otherwise the answer is 0. In C, exclusive disjunction is marked with „^“. This is all one needs to know to change single bits. The theory alone is probably not enough, though, and that is why there are some typical examples with registers in the next few paragraphs.

=== Setting a Single Bit High === [Setting a single bit high] To set one or more bits in a register high (1) a logical addition operation is needed. One of the operands of the operation must be the register and the other a binary number, where the only high bit is the one that needs to be set high in the register. This binary number is called a bitmask. Below is the C code for the operation shown on the right:

Let's suppose REG = 0x0F

REG = REG | 0x11; // First method
REG |= 0x11;      // Second method
// Now REG = 0x1F

Setting a Single Bit Low

Setting a single bit low

To set one or more bits in a register low (0) a logical multiplication operation is needed. One operand of the operation must be the register and the other a bitmask, in which the only low bit is the one that needs to be set low in the register. Below is the C code for the operation shown on the right:

// Let's suppose REG = 0x0F
REG = REG & 0xFE; // First method
REG &= 0xFE;      // Second method
// Now REG = 0x0E

 

Inverting a Single Bit

Inverting a single bit

To invert one or more bits in a register an exclusive disjunction operation is required. One of the operands of the operation must be the register and the other a bitmask, where the only high bit is the one that needs to be inverted in the register. Below is the C code for the operation shown on the right:

// Let's suppose REG = 0x0F
REG = REG ^ 0x11; // First method
REG ^= 0x11;      // Second method (use only one per inversion)
// Now REG = 0x1E

Inverting the Whole Register

Inverting all bits

To invert all bits in a register, a negation operation is used. This operation is unary, which means it has only one operand. Below is the C code for the operation shown on the right:

// Let's suppose REG = 0x0F
REG = ~REG;
// Now REG = 0xF0

Reading the Value of a Single Bit

Reading the value of a bit

To read one or more bits from a register the same operation is required as was used for setting a bit low - logical multiplication. One of the operands of the operation must be the register and the other a bitmask, where the only high bit is the one that needs to be read from the register. Below is the C code for the operation shown on the right:

// Let's suppose REG = 0x0F
unsigned char x = REG & 0x01;
// Now x = 0x01

 

Shifting a Bit

Many programming languages actually have a few additional bitwise operations, which make it easier for programmers. These are bit shifting operations that shift bits left or right in a binary number. The main advantage of shift operations in dealing with registers is their ability to convert bit ranks to bitmasks and vice versa.

Shift left

The image on the right shows a shift-left operation. Although bit shifting is not a logical operation and has no corresponding symbol, in C it is marked as „>“ in C. Right-shift is used to get the logical value of a bit from a bitmask. A previous example showed how to read the value of a single bit. Let's suppose the bit to be read is not of the lowest rank, but for example of rank 5. In this case, the result would be either 0x20 or 0x00, but sometimes a result of 1 or 0 is needed and that is when the right-shift comes to the rescue. The example operation on the right looks like this in C:

Let's suppose REG = 0x20 unsigned char x = REG » 5; Now x = 0x01 (or simply 1)

If a bit is shifted right from the lowest rank or left from the highest rank by the bit shifting operation, it disappears. Some programming languages also have rotating bit shift operations, where the bit doesn't disappear, but moves from the lowest rank to the highest or vice versa. C doesn't have that kind of bit-shift operations, but they can be written by the programmer if needed.

All bit operations work with not only registers, but with variables and constants as well. The latter can of course only be used as operands and not the result.

AVR Registers

To actually do anything with the microcontroller's registers, one needs to know how to use that particular microcontroller. Each microcontroller comes with one or several datasheets, which describe the whole structure and functionality of the microcontroller. The datasheet also describes the registers. The following will help understand the register descriptions in AVR datasheets.

One of AVRs registers from its datasheet

The image shows ATmega128 microcontroller's UCSRnA register, which stands for „USART Control and Status Register A“. This register is used to configure AVR's USART module and read its states. All AVR register names are written in capital letters, but as the reader might notice, the register name contains also a lower case n. A lower n is used to mark some module's index. Since ATmega128 has 2 almost identical USART modules, they are not described twice, but only once and the n must be read as 0 or 1 by the user. Therefore ATmega128 has registers UCSR0A and UCSR1A.

The content of the register is marked by an 8-slot box with a bold line around it. Each slot marks one bit. Bit ranks are marked above the box - increasing from right to left. Since AVR is an 8-bit microcontroller, most of the registers are 8-bit as well. There are some exceptions, a few registers are 16-bit, but they actually consist of two 8-bit registers. Just as each register has a name, each bit in the register also has a name - just like the buttons on a tape player. Each bit is described in the datasheet. Bit names are abbreviations as well and the lower n must be substituted with the module's index, just like with register names. Some registers don't use all 8 bits, in this case the bit's slot is marked with a hyphen.

Below the register's bits are two lines, which state whether the bit is readable (R), writable (W) or both (R/W). For example, the status bits can't be overwritten and even if it's attempted in the program, the bit will remain unchanged. If the bit is marked as writable, reading it will always result in one specific value stated in the datasheet. The second line specifies the default value of the bit, which it has after the reset of the microcontroller.

While AVR register names point to an actual memory slot address, the bit names hold the rank number of the corresponding bit. Therefore it is necessary to transform the names to bitmasks using a shift operation, in order to manipulate with bits in a register. The following code contains a few example lines for using the USART 0 module's register.

// Set TXC0 bit high
UCSR0A |= (1 

Architecture

AVR has an internal 8-bit data bus, through which the data is moved between the arithmetic logic unit (ALU), status register (SREG), program counter (PC), random access memory (SRAM) and peripherals. The program, an array of commands that is executed in the ALU, comes from an address in the flash memory, specified by the program counter. The ALU has 32 8-bit general purpose registers, which are used as operands when carrying out instructions.

Block diagram of ATmega128

Instruction Pipeline

AVR has a two-stage instruction pipeline. While one instruction is executed, the next is fetched from the program memory. This is why carrying out jump instructions takes 2 cycles on fulfillment of the jump condition. Since the new instruction is always fetched from the next memory address, it is necessary to discard the previously fetched instruction and fetch a new one when jumping to another address, because it was taken from an old, wrong location.

General Purpose Registers

General purpose registers R0-R31 are like buffers for storing and operating with memory and peripheral data. They simplify the architecture of the processor, because they are quickly accessible by the ALU, and the use of the data bus to read operands from the memory is not necessary for every operation. General purpose registers are used for performing all data-related arithmetical and logical operations.

While programming in assembler, it is possible to store the urgent data in general purpose registers. While programming in C and a need to store a variable in a general purpose register arises, the variable is additionally defined as „register“. For example:

register char x;

Instruction Set

The instruction set of most AVRs consists of 90-133 different instructions. ATmega128 has 133 instructions. Instructions have either one, two or no operands. Most instructions take only one cycle to complete, but the more complex ones can use up to 5 cycles. For XMega, the successor of AVR, several instructions have been modified to use less cycles. Most instructions in AVR are used for jumps, moving and comparing data and executing arithmetic calculations. A status register is used for performing calculations and comparisons. It stores the output status of the ALU - whether the result was negative, positive, zero, exceeded the maximum allowed value (8 bits), needed to transfer a bit to the next operation etc (there are a few more complex cases).

This is a piece of code written in Assembler and consists of pure instructions, which adds 5 to the byte at random access memory address $100 (decimal 256). These instructions exist in all AVRs.

ldi r1, 5 ; Load the constant 5 to general purpose register r1 lds r2, $100 ; Load the byte from the memory to register r2 add r2, r1 ; Add the value of r1 to r2 sts $100, r2 ; Write the value of r2 back to the memory

Program Stack

Stack is a data structure, where the last data written to the memory is read out first. AVR's stack can be used while operating with subroutines, interrupts and temporary data. Before executing a subroutine or interrupt, the address in the program counter where the program was interrupted is stored in the stack. When the subroutine or interrupt has finished its execution, this address is read back from the stack and the program continues from the address it left off from before. Storing temporary data in the stack is usually used when dealing with shorter chunks of code, which do not require reserved memory throughout the execution of the program. Simpler assembler programs are usually written so that it is not necessary to use the stack, but if the program contains a lot of variables and functions, the compilers automatically make use of it.

The stack of MegaAVR series microcontrollers is physically located in the random access memory. Some tinyAVR series devices do not have a random access memory at all and the stack is realized as a separate, quite limited memory unit. Typically there are no compilers for devices with no random access memory.

To program in a high level language (Pascal, C, C++), it is not necessary to be familiar with the inner workings of the microcontroller, because the compiler is capable of selecting general purpose registers and instructions by itself, but knowing what goes on in the controller is certainly beneficial. It is necessary to know the instructions of the microcontroller when developing time-critical applications, where the operations have to be completed in a limited amount of cycles.

Clock

As with most digital electronics, an AVR also works at a constant frequency. A constant frequency assures the reliability of data exchange throughout the device. There are several methods for generating a clock signal for an AVR.

Internal RC Oscillator

Using an RC oscillator

This is a internal clock generator, which does not need any external components. Its main disadvantages are low frequency and inaccuracy.

External RC Oscillator

Works on the same principal as an internal RC oscillator and has no significant advantage over the internal one.

Crystal Oscillator

Using a crystal oscillator

Crystal oscillators use a crystal (usually quartz) that vibrates at its resonant frequency in the electric field and has a piezoelectic quality to produce an electric field during mechanical deformation (vibration). Crystal oscillators enable a precision of nearly 0.001%, which does not depend on the temperature.

Ceramic Resonator

Ceramic resonators are similar to crystal oscillators, but are made from cheaper piezoelectric materials. Ceramic resonators are typically smaller than crystal oscillators, but are also less precise (~0.5%) and more sensitive to temperature changes.

External Clock Signal

Using an external clock signal

An external clock signal can be generated with any device, provided that the frequency and amplitude (voltage) are in the correct range. For example, an external clock signal generator can be used to provide a clock signal to several microcontrollers at once.

Interrupts

Interrupts in AVR can be caused by counters, communication interfaces, analog-to-digital converters, comparators, special input-output pins and several other functions, depending on the controller. Any interrupt can be allowed or disallowed by the unit that generates it. Regardless of the interrupt being allowed or disallowed, there is a 1-bit field (interrupt flag) in the corresponding unit of the controller, which is marked as true when the interrupt condition is fulfilled. If the interrupt flag is changed to true and the interrupt is allowed, the controller starts to execute the code specified for this interrupt.

Every interrupt in the AVR microcontroller is tied to a specific event. Each event has a flag bit in the status register, which marks the occurring of the event. Events are also tied to interrupt mask registers and the corresponding bits. If the event's interrupt bit is left unmasked and an event occurs, the processor halts executing the current program for a few duty-cycles and begins executing the interrupt program. After the interrupt program has been executed, the processor resumes executing the paused main program.

To use interrupts with the AVR LibC library, it is necessary to include interrupt.h. The code that gets executed upon interrupt is written after the „ISR“ keyword. The text between the brackets after „ISR“ is the name of the interrupt. The following is a C language example:

#include

ISR(XXX_vect) {

// Do something

}

Global allowing of all interrupts is configured from the control and status register SREG. The option to allow or disallow all interrupts at once is there to help protect data. Since interrupts disrupt the execution of the main program, some data used by the main program may be disturbed or corrupted in the process. Situations like this can be avoided by simply disallowing all interrupts before processing such delicate data. Disallowing interrupts globally is easy, if it can be done by changing only one register (SREG). After the critical part of the program has been executed, the interrupts can easily be allowed again and all the interrupts that would have fired in the meantime are executed.

 

Let's suppose there is a 16-bit variable in use in the program, which is changed by both the main program and the interrupt program and the value of this variable is later given to another variable:

#include

Global 16-bit variables x and y unsigned short x, y; A random interrupt that changes the value of x ISR(XXX_vect) {

x = 0x3333;

}

int main() {

// Give a value to x
x = 0x1111;
// Allow interrupts globally
sei();
// Give the value of x to y
y = x;	

}

The program itself is very simple - first, variable x is given a value of 0x1111 and later, its value is given to variable y. If an interrupt occurs between those two operations, x gets a value of 0x3333. By logic, variable y can have two possible values by the end of the program, but on an 8-bit AVR there is also a third option. This is because 8-bit architecture needs 2 cycles to move 16-bit data and therefore a badly-timed interrupt can corrupt the integrity of the data. Consequently, y can have a value of 0x1111 or 0x3333, but it can also have a value of 0x3311 at the end of the program. To avoid getting the third, unwanted value, all interrupts should be temporarily disallowed before performing operations that take more than 1 cycle.

In the following example, the value of x is given to y using a safe method:

// Disallow interrupts globally
cli();
// Give the value of x to y
y = x;
// Re-allow all interrupts again
sei();

Digital Inputs/Outputs

All the buses on an AVR are both readable and writable, if they are used in the default logical input/output (I/O) mode. AVR buses are named as letters from the beginning of the Latin alphabet: A, B, C etc. Some AVRs might not have bus A, though, if bus B exists. Each bus is 8-bit and each bit usually has its own pin on the controller. Pins are counted with numbers starting from zero. For both directions on the bus, there are two separate registers. In addition, there is a register to decide the real direction of the bus, where a bit value of 1 marks the bus as output and 0 as input. Altogether, each bus has three registers:

  • PORT - for setting the output value of the bus.
  • PIN - for reading the input on the bus.
  • DDR - for setting the direction of the bus.

Task: make pins 0-3 on bus B inputs, pins 4-7 outputs, set pin 5 high and read the values of pins 0-3 to a variable. The C code for it looks like this:

#include

int main() {

unsigned char x;
// Pins 0-3 as inputs, 4-7 as outputs
DDRB = 0xF0;
// Set pin five as high
PORTB |= (1 

External Interrupts

External interrups are one of the most simple peripheral functions. Typically AVRs have 1 to 8 special pins, which are used to cause interrupts in the program when their logical value changes or they are at a certain state. Since this function is usually used to monitor external logical signals, these pins are called external interrupt pins.

To use an external interrupt, the pin has to be configured as a standard IO input (it can also be used as an output, but in this case the interrupt can only be created by the controller itself). It is necessary to allow receiving interrupts and specify the condition that causes the interrupt to fire in the external interrupt configuration register. There are four possible conditions:

  • Logical zero (voltage of 0V)
  • Change in the logical value
  • Descending front - logical change from one to zero.
  • Rising front - logical change from zero to one.

When the mode is set to logical zero, the interrupt will fire continuously as long as the pin has a value of zero. During this period the execution of the main program is stopped.

Grouped by principle, there are two types of interrupts: synchronized to the controller's clock and asynchronous. Synchronized interrupts work by remembering the values of the inputs, which means that the changes in logical values are found by comparing values read during two different clock cycles. If the logical changes in the signal happen faster than the controller's duty-cycle, the interrupts either fire incorrectly or are skipped altogether. Asynchronous interrupts do not depend on the controller's clock and enable detecting faster changes in the external signal as well - the logical level must still be constant for at least 50 ns. ATmega128 has 4 synchronized and 4 asynchronous external interrupts.

 

Task: Make ATmega128 pin number 9 (pin 7 on bus E) fire an interrupt if its value is changed. This pin corresponds to the INT7 external interrupt, which is synchronous.

#include

The code of the external interrupt ISR(INT7_vect) { Do something }

int main() {

// Change pin 7 on bus E to an input by changing bit 7 to zero
DDRE &= ~(1 

Analog-to-digital Converter

Analog-to-digital converter (ADC) transforms an analog voltage value to a digital value. The allowed voltage range on an ADC input of an AVR microcontroller is 0 to 5.5 V. The size of the digital value is 10 bits, but its precision is ±2 units. The error may be even larger, if the microcontroller's supply voltage is not protected from interference. AVR has a separate voltage supply and comparison voltage pin for ADC. The separate supply voltage helps to cut down the interference and it may not differ more than 0.3 V from the main supply voltage. Comparison voltage defines the maximum digital value. For example, if the comparison voltage is 3 V then an input with the same voltage will read as 210 - 1 (1023).

AVR ADC works on the principal of successive approximation. In short, the measured voltage is compared to specific voltage levels and the results are reported as a bit array. This method is relatively slow, as each bit in the final result is calculated separately. AVR spends 13 clock cycles for each measuring, except the first (on start-up), which takes 25 cycles. These cycles are not the controller's duty cycles though, but instead special cycles allocated to the ADC unit by the frequency divider. The ADC frequency should be 50-200 kHz to achieve maximum precision, on higher frequencies the precision fades. In some cases it is more important to get a large number of readings instead of maximum precision, in which case using a larger frequency is totally justified. According to AVR documentation, one measuring takes 13-260 µs.

The measured value can be read as an 8- or 10-bit value. Since AVR itself is an 8-bit device, it has two 8-bit registers for storing the ADC values. It is possible to specify in the settings whether the first two or the last two bits go to a separate register. If the two younger bits, which characterize the result less, are separated, the result can be read as an 8-bit value - a combination like that is called a left-aligned result. The other combination, where both registers are read and the value is in 10-bit format, is called a right-aligned result.

A typical AVR has 8 analog voltage input channels, ATtiny series have only a few, some ATmega devices have 16, but there is always only one converter. To make it possible to use different inputs, the device has a built-in multiplexer. The input of the multiplexer is definable using a special register. The ADC unit has a few more properties: using the processor's sleep mode for converting to reduce the interference and the option to use an internal fixed comparison voltage (usually 2.65 V, in some models 1 V).

 

Task: measure the voltage in ADC channel 3 of an ATmega128. The voltage is in range of 0-5 V and the result should be at 8-bit precision.

#include

int main() {

unsigned char result;
// Choose AREF pin for the comparison voltage
//   (it is assumed AREF is connected to the +5V supply)
// Choose channel 3 in the multiplexer
// Left align the result
ADMUX = (1 

/home/www/roboticlab/homelab_data/pages/en/avr/dac.txt— MISSING PAGE —

Counters/Timers

Counters, which in some sense can be called timers, are one of the most important sub-functions of a microcontroller. These enable to precisely time processes, generate signals and count events. A counter converts the number of input cycles to a binary value using an array of triggers. The maximum number of counted cycles depends on the length of this array, and this is marked by the length of the binary code. AVR has 8- and 16-bit counters. If a timer has reached its maximum value (255 in 8-bit and 65535 in 16-bit counters), the next cycle will generate an overflow and the counter resets back to 0. A counter's clock signal can come from the clock signal of the microcontroller, and in this case it is possible to decrease its value using a prescaler. Some AVRs have an internal independent clock signal generator, which can be modified to run faster using a frequency multiplier. Counters also differ in application cases and work modes.

Counter's Default Mode

In the default mode, a counter does nothing more than continually count sequential numbers. Its value can, of course, be read and changed from the program at any time. The only additional function in the default mode is to cause an interrupt on counter overflow. The default mode is typically used to execute a section of the program at certain intervals.

Task: Make an 8 MHz ATmega128 fire an interrupt every 10 ms (frequency 100 Hz). For this task, the 8-bit counter 0 is suitable.

#include

ISR(TIMER0_OVF_vect) {

// Give the counter such a value
// that the next overflow occurs in 10 ms.
// Formula: 256 - 8 MHz / 1024 / 100 Hz = 177,785 = ~178
TCNT0 = 178;

}

int main() {

// To make the first overflow interrupt fire in 10 ms as well,
// the counter needs to be initialized here.
TCNT0 = 178;
// Prescaler value 1024
TCCR0 = 0x07;
// Allow overflow interrupts
TIMSK |= (1 

USART

USART is a universal synchronous serial interface; UART, is a simplified version - universal asynchronous serial interface. The difference being that USART also uses a clock signal line to synchronize data, but UART only uses data lines. AVR's USART allows the use of full duplex communication, 5- to 9-bit data words (8-bit word = byte), 1 or 2 stop bits, three parity modes and a wide variety of baud rates. AVR microcontrollers typically have up to 2 USART interfaces, although some may have no USART. Data transmission is performed one word at a time - AVR converts the word it gets from the user to bits on the hardware level and transmits it independently and vice versa. The user controls USART by reading and writing configuration, status and data registers.

Every configuration option has corresponding registers, which are quite easy to configure using the datasheet. The baud rate, though, is a bit more difficult to set. The clock signal for data transmission is generated from the controller's own clock, and the user can specify a number from 1 to 4096, by which the controller's clock cycle is divided. The result is additionally divided by 2, 8 or 16, depending on the mode. The problem is, not all clock frequencies can be divided so that the result is a standard baud rate. With some frequencies, the baud rate can differ from the standard by up to 10%. AVR datasheets contain tables with typical clock frequencies, baud rates, the needed multiplier to reach that baud rate and the possible calculation error.

Since data transmission takes place independently of the processor and much slower, it is necessary to confirm that the interface is ready for the next word before transmitting. This can be done by keeping an eye on the transmit buffer's ready bit, which signifies if the buffer is ready to accept a new word or not. The controller starts with the ready bit enabled. As soon as a word is transmitted and the buffer is empty, the ready bit is set high.

The arrival of a word is signified also by a special status bit. In addition to that, there are status bits to signify framing errors, parity errors and receive buffer overflows. Buffer overflow can occur when the last word is yet to be read from the buffer while a new one arrives - this is why it is always important to read the incoming words to the program as soon as possible, for example, by using an interrupt. There are three possible interrupt reasons: transmit buffer ready, transmit successful and receive successful.

The transmit and receive buffers are physically separate registers, but share the same memory address and name. When writing to the shared register, the data is stored in the transmit buffer, and when reading from it, the data is read from the receive buffer. When using 9-bit words, the 9th bit is transmitted and read using one of the configuration registers.

 

Task: Configure an 8 MHz ATmega128's USART0 interface to transmit 8-bit words asynchronously using 9600 bps baud rate, 1 stop bit and no parity bits. Send the symbol „X“.

#include

int main() {

// Set baud rate to 9600 bps. Formula:
//   multiplier = clock frequency / 16 / baud rate - 1
//   UBRR = 8000000 / 16 / 9600 - 1 = ~51
UBRR0H = 0;
UBRR0L = 51;
// Allow transmitting
UCSR0B = (1 

HomeLab Kit

Robotic HomeLab is an ATmega2561 microcontroller based inter-related set of modules that are contained in a portable case. Various mechatronic and robotic experiments and exercises can be carried out with Robotic HomeLab kit, ranging from a simple flashing light to a complex device construction. Robotic HomeLab is primarily intended for schools and universities, as it includes methodological materials and exercises with solutions in addition to hardware. Robotic HomeLab has been integrated into a web environment, which is aimed for students and teachers to boost interaction between each other. In short, the Robotic HomeLab kit is a mobile tools suite with the purpose of learning and practicing at home, school or workplace.

Robotic HomeLab kit has been developed by Tallinn University of Technology and Estonian company ITT Group in cooperation with European partner universities and Leonardo da Vinci program support. Robotic HomeLab modules are bundled into different kits. The basic suite, which teaches simple digital input and output operations, is called Robotic HomeLab Basic kit. The Add-on kit contains a modules and components for sensor, motor and communication experiments. Several additional modules are integrated with Robotic HomeLab kit for advanced study like RFID technology, machine vision and WiFi.

The Robotic HomeLab Basic kit and Add-on kit modules and components can be successfully used as a robot base platform and other mechatronics control systems. Robotic HomeLab versions are constantly evolving and, therefore every now and then please check whether new exercises have been published or module updates have been released. It is also worthwhile to check the version numbers of modules, some of the exercises and examples are available in newer versions. Significant value to Robotic HomeLab is added by VirtualLab and DistanceLab. DistanceLab allows Robotic HomeLab hardware platform to be used through the web.

HomeLab webpage
http://home.roboticlab.eu

DistanceLab webpage
http://distance.roboticlab.eu

Robotic HomeLab Hardware

The modules of the Robotic HomeLab are divided into different kits, allowing one to select the best option for the needs of a student or school. The simplest set is the Robotic HomeLab Basic kit including the components to carry out the basic microcontroller experiment. In addition to the microcontroller, the kit consists of a User Interface module with LCD display. Together with the Robotic HomeLab Basic kit, the Robotic HomeLab Add-On kit can be used; this includes different types of motors and sensors together with accessories and Communication module. The Robotic HomeLab Add-On kit cannot be used separately from the Robotic HomeLab Basic kit as the microcontroller is not included in the Add-On kit. In addition the RFID and Machine Vision modules are available. The Robotic HomeLab Basic kit together with the Robotic HomeLab Add-On kit is convenient to use and carry to home for the robotic experiments.

Robotic HomeLab generations

Robotic HomeLab III generation

The modules of the Robotic HomeLab are divided into different kits, allowing one to select the best option for the needs of a student or school. The simplest set is the Robotic HomeLab Basic kit including the components to carry out the basic microcontroller experiment. In addition to the microcontroller, the kit consists of a User Inteface module with LCD display and Combo module. Together with the Robotic HomeLab Basic kit, the Robotic HomeLab Add-On kit can be used; this includes different types of motors and sensors together with accessories. The Robotic HomeLab Add-On kit cannot be used separately from the Robotic HomeLab Basic kit as the microcontroller is not included. In addition the RFID and Machine Vision modules are available. The Robotic HomeLab Basic kit together with the Robotic HomeLab Add-On kit are convenient to use and carry to home for the robotic experiments.

Robotic HomeLab Basic kit

Robotic HomeLab Basic kit

  • AVR ATxmega128A1U development board with SD card reader
  • User interface module
    • 3 x LED (green, yellow and red)
    • 3 x buttons
    • 7-segment display
    • Graphical LCD (128×160 px, 24-bit RGB)
    • Speaker
    • Potentiometer (11 bit - 2048)
    • Light dependent resistor
    • Thermistor
    • Microphone
  • Combo module
    • 4 x H-bridge DC motor drivers
    • 1 x unipolar stepper motor driver
    • 4 x Servo / Encoder
    • Connections for sensors
    • Wireless module connection with Bluetooth module
  • USB cable
  • Micro SD card with USB adapter
  • Example exercises with C-source code (examples)
  • Software library
  • Power supply
  • Multimeter
  • Software for programming in Assembler and C language
  • Portable case

 

Robotic HomeLab Add-On kit

Robotic HomeLab Add-On kit

Motors
  • 2 x DC motor(w/ gearbox, wheel and coder)
  • RC mini servomotor
  • Stepper motor (unipolar)
Sensors
  • Ultrasonic distance sensor with cable
  • Infrared distance sensor with cable
  • Line following module
  • Passive infrared sensor (motion sensor)
  • Humidity and temperature sensor
  • Pressure sensor
  • Accelerometer
Expansion modules
  • Ethernet module
  • Real time clock (RTC) module
Prototyping equipment
  • Solderless prototyping board
  • 20 x jumper cables

 

Robotic HomeLab additional modules

Additional modules are not packed into the cases but can be directly connected with Robotic HomeLab Communication module. Practical examples and exercises are provided for these modules.

  • High frequency RFID module with tags
  • Machine vision module
  • WiFi module
  • GPS module

Robotic HomeLab kits can be used in addition to experiments as a base controller for a robotic or any other mechatronics system. Robotic HomeLab versions are in constant development so check for updates. Also note the version number because some examples or exercises work with only newer versions.

Connecting Robotic HomeLab modules

Connection table
AVR pinFunctionHeader groupDevice AVR pinFunctionHeader groupDevice
PA0ADC0PA-PB-PFADC 0 PF0OC0A/SDAPA-PB-PFI/O Port
PA1ADC1PA-PB-PFADC 1 PF1OC0B/SCLPA-PB-PFI/O Port
PA2ADC2 / DAC0PA-PB-PFADC 2 PF2OC0C/RXD0PA-PB-PF
PA3ADC3 / DAC1PA-PB-PFADC 3 PF3OC0D/TXD0PA-PB-PF
PA4ADC4PA-PB-PFADC 4 PF4SD card SS SD card
PA5ADC5PA-PB-PFADC 5 PF5SD card MOSI SD card
PA6ADC6PA-PB-PFADC 6 PF6SD card MISO SD card
PA7ADC7PA-PB-PFADC 7 PF7SD card SCK SD card
PB0ADC8PA-PB-PFADC 8 PH0 PH-PJ-PKButton S3
PB1ADC9PA-PB-PFADC 9 PH1 PH-PJ-PKButton S2
PB2ADC10 / DAC0PA-PB-PFADC 10 PH2 PH-PJ-PKButton S1
PB3ADC11 / DAC1PA-PB-PFSpeaker PH3 PH-PJ-PKLED 3
PB4ADC12PA-PB-PFMicrophone PH4 PH-PJ-PKLED 2
PB5ADC13PA-PB-PFLDR PH5 PH-PJ-PKLED 1
PB6ADC14PA-PB-PFNTC PH6 PH-PJ-PK
PB7ADC15PA-PB-PFPOT PH7 PH-PJ-PK
PC0OC0A/SDAPC-PD-PEDC 1A PJ0 PH-PJ-PKStepper 1
PC1OC0B/SCLPC-PD-PEDC 2A PJ1 PH-PJ-PKStepper 2
PC2OC0C/RXD0PC-PD-PEDC 3A PJ2 PH-PJ-PKStepper 3
PC3OC0D/TXD0PC-PD-PEDC 4A PJ3 PH-PJ-PKStepper 4
PC4OC1A/SSPC-PD-PEServo 1 PJ4 PH-PJ-PKDC 1B
PC5OC1B/MOSIPC-PD-PEServo 2 PJ5 PH-PJ-PKDC 2B
PC6RXD1/MISOPC-PD-PEXbee RX PJ6 PH-PJ-PKDC 3B
PC7TXD1/SCKPC-PD-PEXbee TX PJ7 PH-PJ-PKDC 4B
PD0OC0A/SDAPC-PD-PEENC 1 PK0 PH-PJ-PKLCD CS
PD1OC0B/SCLPC-PD-PEENC 2 PK1 PH-PJ-PKLCD RS
PD2OC0C/RXD0PC-PD-PEUART RX PK2 PH-PJ-PKLCD RST
PD3OC0D/TXD0PC-PD-PEUART TX PK3 PH-PJ-PKLCD BL
PD4OC1A/SSPC-PD-PE PK4 PH-PJ-PK7-seg MOSI
PD5OC1B/MOSIPC-PD-PE PK5 PH-PJ-PK7-seg SCK
PD6D- USB PK6 PH-PJ-PK7-seg LATCH
PD7D+ USB PK7 PH-PJ-PK
PE0OC0A/SDAPC-PD-PEI/O Port PQ0 PA-PB-PFUSB LED
PE1OC0B/SCLPC-PD-PEI/O Port PQ1 PA-PB-PFUSB State
PE2OC0C/RXD0PC-PD-PEI/O Port PQ2 LED 0
PE3OC0D/TXD0PC-PD-PEI/O Port PQ3 Button S0
PE4OC1A/SSPC-PD-PEI/O Port PDIPDI_DATAPDIPDI Data
PE5OC1B/MOSIPC-PD-PELCD SDA RESETPDI_CLOCK / RESETPDIPDI Clock and Reset
PE6RXD1/MISOPC-PD-PEI/O Port PROXTAL2 XTAL
PE7TXD1/SCKPC-PD-PELCD SCL PR1XTAL1 XTAL

Robotic HomeLab II generation

The modules of the Robotic HomeLab are divided into different kits, allowing one to select the best option for the needs of a student or school. The simplest set is the Robotic HomeLab Basic kit including the components to carry out the basic microcontroller experiment. In addition to the microcontroller, the kit consists of a User Interface module with LCD display. Together with the Robotic HomeLab Basic kit, the Robotic HomeLab Add-On kit can be used; this includes different types of motors and sensors together with accessories and Communication module. The Robotic HomeLab Add-On kit cannot be used separately from the Robotic HomeLab Basic kit as the microcontroller is not included in the Add-On kit. In addition the RFID and Machine Vision modules are available. The Robotic HomeLab Basic kit together with the Robotic HomeLab Add-On kit are convenient to use and carry to home for the robotic experiments.

Robotic HomeLab Basic kit

Robotic HomeLab Basic kit





  • AVR ATmega2561 development board, including Ethernet, SD card reader and integrated JTAG programmer
  • User interface board (buttons, LEDs, Graphical LCD, 7-segment indicator and buzzer)
  • USB cable
  • Example exercises with C-source code (examples)
  • Software library
  • Power supply
  • Multimeter
  • Software for programming in Assembler and C language
  • Portable case

Robotic HomeLab Add-On kit

Robotic HomeLab Add-On kit
Sensor Module
  • Analogous sensor and low-pass filter combined board with on-board sensors (temperature sensor, light intensity sensor, potentiometer and mic)
  • Ultrasonic distance sensor SRF05 with cable
  • Infrared distance sensor with cable
Motor Module
  • DC motor (w/ gear and encoder)
  • RC servo motor
  • Stepper motor (bipolar or unipolar stepper)
  • Motor driver board
  • Power supply divider
Communication module
  • Communication board, 2xRS232
  • ZigBee or Bluetooth wireless unit

Robotic HomeLab additional modules

Additional modules are not packed into the cases but can be directly connected with Robotic HomeLab Communication module. Practical examples and exercises are provided for these modules.

RFID Module
  • High frequency RFID reader
  • Tag (2)
  • Cable
Machine Vision Module
  • Intelligent camera module (CMUcam3)

Robotic HomeLab I generation

Robootika Kodulabori moodulid on jagatud erinevatesse komplektidesse, võimaldades valida sobivaima, sõltuvalt õpilase või kooli eesmärkidest. Lihtsaim komplekt on Robootika Kodulabori baaskomplekt, mis sisaldab endas kõike vajalikku mikrokontrolleri kasutamiseks ja lisaks Digitaalset sisend-väljund plaati koos LCD ekraaniga. Robootika Kodulabori baaskomplektiga saab kasutada Robootika Kodulabori lisakomplekti, mis sisaldab mootorite ja andurite plaate, erinevat tüüpi mootoreid, andureid ning nende tarvikuid. Robootika Kodulabori lisakomplekt töötab koos Robootika Kodulabori baaskomplektiga. Iseseisvalt lisakomplekti kasutada ei saa, sest see ei sisalda mikrokontrollerit.

Kodulabori baaskomplekt

Robootika Kodulabori baaskomplekt


  • AVR ATmega128 arendusplaat koos
  • JTAG programmaatora
  • Digitaalne sisend-väljund moodul (nupud, LED-id,7-segment-indikaator)
  • LCD ekraan
  • USB kaabel
  • Näiteülesanded koos C-lähtekoodiga (näidisharjutus)
  • Tarkvarateek
  • Toiteplokk
  • Multimeeter
  • Tarkvara assembler- ja C-keeles programmeerimiseks
  • Kaasaskantav kohver

 

Robootika Kodulabori Andurite ja Mootorite lisakomplekt

Robootika Kodulabori lisakomplekt
Mootorite moodul
  • Alalisvoolumootor (reduktori ja koodriga)
  • RC servomootor
  • Samm-mootor
  • Mootorite ajuriplaat
  • Toitejagur
Andurite moodul
  • Analoogandurite ja madalpääsfiltritega kombineeritud plaat koos anduritega (temperatuuriandur, valgustugevuse andur, potentsiomeeter ja mikrofon)
  • Ultraheli kaugusandur SRF05 koos kaabliga
  • Infrapuna kaugusandur SHARP koos kaabliga

 

Kodulabori Täiskomplekt

Kodulabori Täiskomplekt on mõeldud õpetajale. See sisaldab kõik komponente Kodulabori baaskomplektis ja Kodulabori lisakomplketist ning lisaks järgmisi mooduleid:

Robootika Kodulabori täiskomplekt
Kommunikatsiooni moodul
  • Kommunikatsiooni moodul (Bluetooth)
RFID moodul
  • Kõrgsageduslik RFID lugeja
  • Märk (2 tk)
  • Kaabel
Masinnägemise moodul
  • Intelligentne kaameramoodul (CMUcam3)

Controller module

The Controller module in Robotic HomaLab kit is a development board equipped with AVR ATmega series microcontroller and peripherial devices.

Robotic HomeLab kit has currently three generation Controller modules. Below, you can choose a suitable Controller module documentation.

ATXmega128A1U (version 3.x)

ATmega2561 (version 1.x)

atmega2561.jpg


ATmega128

 

Controller module ATmega2561 v1.x

The main module of the HomeLab is a controller development board (controller board) equipped with the AVR ATmega2561 microcontroller. In addition to the microcontroller, the board consists of several peripherals, voltage stabilizer, connectors, JTAG programmer, Ethernet, SD memory card slot. The controller board has the following features:

  • ATmega2561-16AU microcontroller
    • 8-channel 10-bit A/D converter
    • 256 kB Flash memory (program memory)
    • 4kB EEPROM memory (data memory)
    • 6 channel programmable PWM
  • Integrated JTAG programmer (based on FTDI2232)
  • 14,7456 MHz clock
  • Ethernet module with RJ45 connector
  • SD memory card slot
  • Status LED (PB7)and Power LED
  • Programmable button (PC2) and reset button
  • All Atmega signals available on three connectors (1: ports D, B, E; 2: ports G, C, A; 3: port F with ADC I/O lines)
  • 2,1 mm power socket
  • Automatic power switch USB or external power supply
  • Built-in voltage stabilizer, with 5 V and 3,3 V output
Controller module

The module is equipped with a AC/DC rectifier circuit and a LDO voltage stabilizer (with low dropout) -an external feeder with voltage stabilization is not needed. The module can be powered with a step down transformer with an output voltage which is greater than 6 volts and lower than 15 volts. In order to reduce power losses it is recommended to use power supply between 6-9V. The POWER LED signalizes a connected feed (“POWER” description on the board). All ATmega2561 signals are available on three connectors on the edge of the board. Connectors pin assignment is described in the next part of this instruction. It includes full descriptions of ATmega2561 pins and their alternative functions. The module is equipped with a microprocessor reset circuit (when power on) and a reset button for a microprocessor restart. A microprocessor can be programmed with an on-board JTAG programmer over USB or with an ISP interface. To the seventh pin of port B (named as PB7) the status LED (described as PB7 on the board) is connected. This LED can be used as a status indicator of application software. Low state on PB7 pin causes the status LED to be lit. The module is equipped with SD memory card slot, where it can be used as a standard microSD memory card. The memory card is connected to the microcontroller via the ISP interface and can be used to store data where data must be maintained even if the power supply is removed.

Components on the Controller board
Connector Pins and Functions

NrPinAlternative function / Description
1VCC- +5 V
2GND- GND
3REFAREFAnalog Reference Voltage For ADC
4GND- GND
5PF0ADC0ADC Input Channel 0
6GND-GND
7PF1ADC1ADC Input Channel 1
8GND-GND
9PF2ADC2ADC Input Channel 2
10GND-GND
11PF3ADC3ADC Input Channel 3
12GND-GND

 

NrPinAlternative function / Description
1 PD7T2 Timer/Counter2 Clock Input
2 PD6T1 Timer/Counter1 Clock Input
3 PD5XCK1 USART1 External Clock Input/Output
4 PD4IC1 Timer/Counter1 Input Capture Trigger
5 PD3INT3/TXD1 External Interrupt3 Input or UART1 Transmit Pin
6 PD2INT2/RXD1 External Interrupt2 Input or UART1 Receive Pin
7 PD1INT1/SDA External Interrupt1 Input or TWI Serial Data
8 PD0INT0/SCL External Interrupt0 Input or TWI Serial Clock
9 VCC- +5V
10GND- GND
11PB7OC0A/OC1C/PCINT7Output Compare and PWM Output A for Timer/Counter0, Output Compare and PWM Output C for Timer/Counter1 or Pin Change Interrupt 7
12PB6OC1B/PCINT6Output Compare and PWM Output B for Timer/Counter1 or Pin Change Interrupt 6
13PB5OC1A/PCINT5Output Compare and PWM Output A for Timer/Counter1 or Pin Change Interrupt 5
14PB4OC2A/PCINT4Output Compare and PWM Output A for Timer/Counter2 or Pin Change Interrupt 4
15PB3MISO/PCINT3SPI Bus Master Input/Slave Output or Pin Change Interrupt 3
16PB2MOSI/PCINT2SPI Bus Master Output/Slave Input or Pin Change Interrupt 2
17PB1SCK/PCINT1SPI Bus Serial Clock or Pin Change Interrupt 1
18PB0SS/PCINT0SPI Slave Select input or Pin Change Interrupt 0
19PE7INT7/IC3/CLK0 External Interrupt 7 Input, Timer/Counter3 Input Capture Trigger or Divided System Clock
20PE6INT6/T3 External Interrupt 6 Input or Timer/Counter3 Clock Input
21PE5INT5/OC3CExternal Interrupt 5 Input or Output Compare and PWM Output C for Timer/Counter3
22PE4INT4/OC3BExternal Interrupt4 Input or Output Compare and PWM Output B for Timer/Counter3
23PE3AIN1/OC3AAnalog Comparator Negative Input or Output Compare and PWM Output A for Timer/Counter3
24PE2AIN0/XCK0Analog Comparator Positive Input or USART0 external clock input/output
25PE1PDO/TXD0 ISP Programming Interface Data Output or USART0 Transmit Pin
26PE0PDI/RXD0/INT8 ISP Programming Interface Data Input, USART0 Receive Pin or Pin Change Interrupt 8

NrPinAlternative function / Description
1 GND- Gnd
2 VCC- +5 V
3 PA0AD0External memory interface address and data bit 0
4 PA1AD1External memory interface address and data bit 1
5 PA2AD2External memory interface address and data bit 2
6 PA3AD3External memory interface address and data bit 3
7 PA4AD4External memory interface address and data bit 4
8 PA5AD5External memory interface address and data bit 5
9 PA6AD6External memory interface address and data bit 6
10PA7AD7External memory interface address and data bit 7
11PG4TOSC1RTC Oscillator Timer/Counter2
12PG5OC0BOutput Compare and PWM Output B for Timer/Counter0
13PG2ALEAddress Latch Enable to external memory
14PG3TOSC2RTC Oscillator Timer/Counter2
15PC6A14External Memory interface address bit 14
16PC7A15External Memory interface address bit 15
17PC4A12External Memory interface address bit 12
18PC5A13External Memory interface address bit 13
19PC2A10External Memory interface address bit 10
20PC3A11External Memory interface address bit 11
21PC0A8 External Memory interface address bit 8
22PC1A9 External Memory interface address bit 9
23PG0WR Write strobe to external memory
24PG1RD Read strobe to external memory
25GND- GND
263V3- +3,3 V

 

Connecting

When connecting the controller module with other modules or devices, you must first make sure that the controller module power supply is not connected. Modules and devices must be connected to each other with care. It is important not to use excessive force, wrong handling may damage the module. For programming and to power with low currency (less than 500mA) you must only connect the controller module with a PC using an USB port. If you are using modules that need to use a greater current than 500 mA, you must use a separate power source. If a controller module is connected to a separate power source, then the module automatically does not use USB a power supply.

Controller module connected to power supply and programmer

User Interface Module

Please select the module version:


Version III 1.0


Version 5.3


Version 5.0


Version 3


 

User Interface module

The User Interface module is designed for simple tasks and basic process control. Module has three push-buttons and three LEDs, which can be used as digital inputs and outputs of microcontroller. Additionally to simple LEDs the module is equipped with 7-segment indicator, graphical LCD display, alphanumeric LCD outputs and a buzzer. User Interface module is handy to use along with other modules enabling to control the output device behavior, like motors and display the sensor readings. The module is covered with plexiglass to protect the board from accidents.

Module features:

  • Three LEDs: green, yellow and red;
  • Three push-buttons;
  • 7-segment indicator;
  • Graphical LCD;
  • Alphanumeric LCD connector;
  • Buzzer;

Electrical connections

User Interface module is connected to Controller module to ports PA/PC/PG, which includes the 8-pin ports PA and PC and 6-pin port PG.

User Interface module is equipped with three buttons S1, S2, S3 which are connected to ports PC0, PC1, PC2 accordingly. The other end of buttons are connected through the resistors to ground (logical 0). LED1, LED2 and LED3 on the module are connected to the ports PC3, PC4, PC5 accordingly. The anodes of LEDs are connected to the supply (logical 1).

Schematics of buttons and LEDs

User Interface module is equipped with 7-segment indicator, which is connected to the microcontroller ports through the driver A6275. Driver data bus (S-IN) is connected to pin PC6, clock signal (CLK) to the pin PC7 and latch signal (LATCH) to pin PG2.

Schematics of 7-segment indicator

The graphical LCD display on the module is connected to port PA. In parallel the same port has external connector where all pins are aligned according to the standard 2 x 16 alphanumeric LCD 4 bit control. The user can choose whether to use the graphical or alphanumeric LCD. It is not possible to use both at the same time. The graphical LCD's background lighting can be logically controlled by the software. The back-light intensity of the alphanumeric LCD is regulated with on-board resistor and graphical LCD back-light can be controlled by the software. Both LCD displays are connected to port PA but only one at a time can be used. When selecting the alphanumeric LCD the jumper should be removed to avoid random control of graphical LCD background light.

Schematics of LCD

The buzzer is connected with controller board's pin PG5 and with Vcc. It's possible to generate sound with Robotic Homelab library or with your own software.

Schematics of buzzer
Connecting the module

While connecting the module it is suggested to follow the order described below. Before connecting any cables make sure that the power is removed from the Controller board.

  1. Connect the User Interface module with the Controller module gently.
  2. If needed, connect the JTAG programmer with the Controller module.
  3. Connect the power supply with the Controller module.

Combo module

Robotic HomeLab III generation


Version 1.0


Robotic HomeLab II generation

Version 1.3


Version 1.2


Version 1.1


Version 1.0


 

Combo module III

Combo board is designed to connect external devices to the Robotic Homelab Kit. External devices are conditionally divided into three groups: sensors, motors and communication interfaces. Each group of devices has its own set of connectors, which are separated from each other. For example, connectors for sensors are located in the right part of the module, motors plugs are located on the left and communication interface plugs on top of the module.The plugs for sensors and communication interfaces are connected directly to the controller’s corresponding signal pins, but the connectors of motors are connected to the controller’s pins through the drivers. This allows Combo module to drive more powerful motors which are not drivable to the direct microcontroller pins.

Combo board is able to drive following motors:

  • 4 x DC motors
  • 1 x unipolar stepper motor
  • 4 x servomotor

Connect following sensors:

  • 11 x analog
  • 8 x digital
  • 4 x coder

Use the following communication interfaces:

  • UART (3,3 V supply)
  • Bluetooth / ZigBee / RFID / WiFi / GPS wireless communication modules

The default is installed Bluetooth BTBee Pro wireless communication module.

Combo board with BTBee module
Electrical connections

The Combo module plugs are divided into three major groups. The connectors for sensors are located in the right side of the module, motors plugs are located on the left side and communication interface plugs in the top right of the module. The motor connectors are divided into three groups: DC motor, servo motor, and stepper motor. DC and stepper motor feeds come from the Controller module power cord, servo motors feed comes through 5V voltage regulator also from Controller module power cord. Servo motor connector is also multifunctional, which can optionally be connected to the encoder input, which is often used in conjunction with DC motor. Each connector pin is connected to the specific port, supply or ground on the Controller module. The following diagrams illustrate the position of a specific group of pins, connectors and connections with Controller module.

The group of sensors

 
The group of motors

Sensors

= ADC sensor inputs= The Combo module has 11 ADC input for an analog sensors. The sensor inputs are moved into the left part of the sensors connector, where each sensor has a separate GND, +3.3 V power supply and signal pin. GND connection is lowest.

= Digital inputs = Combo board has 8 digital pins where to connect digital sensors. The digital inputs are moved into the right part of the sensors connector

= Supply voltage measurement circuit ADC0 = In addition, it is possible to measure the supply voltage of the Combo module. In this case a jumber could be added to Vbat. ADC0 pin is then connected to a voltage divider. This option can be useful for robots to monitor the battery voltage while driving.

DC_REF schematic
Resistor Value
Higher 6.8k
Lower 1k

= Coder= Coder shares pins of the Servo output to be able to use four servo motors, or obtain feedback from four coders, or share the connector halves. The encoder is connected to Servo - Encoder connector.

Coder connection scheme
AVR pin Signal
PC4(INT0C) Coder
PC5(INT1C) Coder
PD0(INT0D) Coder
PD1(INT1D) Coder

 
= DC motors= DC motors is connected to the DC group of pins. Every pair of pins can control 1 dc motor, thus it's possible to manipulate 4 dc motors. Combo board uses DRV8801 H-bridge to control dc motors. It's possible to manipulate some other device, what can be controlled digitally and it's current is smaller than 1,5 A and voltage does not exceed 16 V, beside dc motor with DC pins (Piezoelectric generator, relay etc).

DC motor connection scheme
AVR pin Signal AVR pin Signal
PC0(OCC0A) Motor 1A PJ4 Motor 1B
PC1(OCC0B) Motor 2A PJ5 Motor 2B
PC2(OCC0C) Motor 3A PJ6 Motor 3B
PC3(OCC0D) Motor 4A PJ7 Motor 4B

= Stepper motors = Stepper motors generally divided into two categories: unipolar- and bipolar stepper motors. Unipolar stepper motors can be connect pins group Unipolar Stepper, where the power cable must be connected to the Vbat pin. The remaining four pins are stepper motor driver coil pins. Bipolar stepper motor can be driven with the DC motor pins where one bipolar stepper motor requires two DC motor driver.

Unipolar stepper connection scheme
AVR pin Signal
PJ0 Winding 1A
PJ1 Winding 2A
PJ2 Winding 1B
PJ3 Winding 2B

= Servomotors= Servo is connected to Servo - Encoder pins. Ground wire (usually black or braun) is connected to the GND pin (lower pin). It's possible to use 4 servomotors at once. Signal pins on the Combo board is directly connected to the controller's timer's output pins.

Servomotor connection scheme
AVR pin Signal
PC4(OCC1A) PWM
PC5(OCC1B) PWM
PD0(OCD0A) PWM
PD1(OCD0B) PWM

Serial interface

The Combo module can be connected to the external UART or SPI devices.

The external UART device Schematics
Wireless module

One of these modules can be connected to the Combo board:

  • XBee/ZigBee module
  • Bluetooth
  • GPS module
  • RFID module
  • Wifi module

All of these module communicate over the UART interface with the microcontroller. By default bluetooth module BluetoothBee Pro is connected to the Combo module..

Wireless connection scheme

Combo board is connected with 4 wireless module's i/o pins, in addition XBee DIO4 is connected to test LED. XBee pin AD5 is connected to the voltage divider for measuring the voltage across the XBee wireless network.

BluetoothBee Pro module

Pin from wireless module Signal Socket
20(MODE) MODE XBEEADC0
19(STATUS) STATUS XBEEADC1
17(A_RST) XADC3 XBEEADC3

XBee module

Pin from wireless module Signal Socket
20(AD0/DIO0) XADC0 XBEEADC0
19(AD1/DIO1) XADC1 XBEEADC1
18(AD2/DIO2) XADC2 XBEEADC2
17(AD3/DIO3) XADC3 XBEEADC3
11(RF_TX/AD4/DIO4) DIO4 test LED (yellow)
15(ASSOC/AD5/DIO5) PWR Connected with robot's power supply
16(RTS/AD6/DIO6) RST Reset pin form controller module

Combo module

Robotic HomeLab III generation


Version 1.0


Robotic HomeLab II generation

Version 1.3


Version 1.2


Version 1.1


Version 1.0


HomeLab Library

HomeLab library is composed of several C language header files (with „.h“ extension) and one static library file (with „.a“ extension„). Upon library installation, all these files are copied to the AVR-GCC subdirectories where the compiler finds them automatically. The user does not have to copy these files to his or her program folder.

HomeLab library source code files

Step-by-step AVR development software installation instructions for Windows and Linux are written in the first chapter of practical examples. Although different practical examples use various parts of the library, all of them must include a static library (“.a„ file) in the project. Only header files can be included selectively. Header files which are directly related to the AVR microcontroller are in the „homelab“ folder, HomeLab module specific files are in the „homelab/module“ folder. Both these folders are in the compiler's root folder, and to include the files from them, less-than and greater-than signs are needed to specify the path. An example of how to include AVR pins and HomeLab motors library header files:

#include #include

If HomeLab library is not used, then the following avrlibc header file needs to be included into the project:

#include

In the HomeLab library, this file is already included in the pin.h file.

HomeLab library installer is freely available on the HomeLab web-page. Users who are interested in customizing the library can also download the source code for it. The following chapters describe the functionality of the library.

Bitwise Operations

Bitwise operations library contains a set of macro functions to do common bit manipulation operations. They are used by the rest of the library and can be used everywhere else. As the macro-functions have no type, they are compatible with any data type.

Bit index is used to specify the bit in the binary number. Indexes are counted from zero, where zero represents the least significant bit (LSB). For example, an 8-bit number has 8 bits with indexes from 0 to 7 and a 16-bit number has 16 bits with indexes from 0 to 15.

Functions

  • bit_mask(bit)

Bit index to bit mask converting. Parameters:

  • bit - Bit index.
  • Returns bit mask.
  • bit_set(value, bit)

Sets a specified bit in the variable. Parameters:

  • value - Variable.
  • bit - Bit index.
  • bit_clear(value, bit)

Clears a specified bit in the variable. Parameters:

  • value - Variable.
  • bit - Bit index.
  • bit_set_to(value, bit, state)

Set a specified bit in the variable to desired state. Parameters:

  • value - Variable.
  • bit - Bit index.
  • state - State (true or false).
  • bit_invert(value, bit)

Inverts a specified bit in the variable. Parameters:

  • value - Variable.
  • bit - Bit index.
  • bit_is_set(value, bit)

Checks whether a specified bit in the variable is set or not. Parameters:

  • value - Variable.
  • bit - Bit index.
  • Returns boolean value true when bit is set and false when bit is cleared.
  • bit_is_clear(value, bit)

Checks whether a specified bit in the variable is cleared or not. Parameters:

  • value - Variable.
  • bit - Bit index.
  • Returns boolean value true when bit is cleared and false when bit is set.

Example

Setting up a third bit in the 8-bit variable b and inverting of the last one.

#include

int main(void) {

unsigned char b = 0x00;
bit_set(b, 2);
bit_invert(b, 7);

}

Source

The following is a shortened version of the bitwise operations library source code.

Functions for handling bits. #define bit_mask(bit) (1 ==== Pins ==== Pins library provides an easy way for operating with AVR digital input-output pins. The user can create a pin related variable and do all the pin operations with that variable. This way there is no need to deal with the register names and bit indexes like it is done while programming in direct register access method. The pin's port and index must be specified only once, so the changes are easy to implement. === Data Types === * pin
Data type to hold pin registers addresses and bit mask. To get the most efficent program,
pin typed variables should be constant, and they should be initialized at the beginning of the program code. Intializing can be done with the macro function PIN, whose first parameter is the port letter (capital A, B, C, etc) and the other one being the pin index (0 to 7). Only existing ports and pins can be used. === Constants === * led_green, led_yellow, led_red - Homelab User interface board LEDs by colour * LED1, LED2, LED3 - Homelab User interface board LEDs by LED numbers * S1, S2, S3 - Homelab User interface board buttons === Functions === * void pin_setup_output(pin pin)
Configures pin as an output. Parameters: *
pin - Pin variable. * void pin_setup_input(pin pin)
Configures pin as an input without pull-up resistor. Parameters: *
pin - Pin variable. * void pin_setup_input_with_pullup(pin pin)
Configures pin as an input with pull-up resistor. Parameters: *
pin - Pin variable. * void pin_set(pin pin)
Sets output pin high. Parameters: *
pin - Pin variable. * void pin_clear(pin pin)
Sets output pin low. Parameters: *
pin - Pin variable. * void pin_toggle(pin pin)
Inverts output pin state. Parameters: *
pin - Pin variable. * void pin_set_to(pin pin, bool value)
Sets output pin to desired state. Parameters: *
pin - Pin variable. * value - Desired state boolean value. * bool pin_get_value(pin pin)
Gets pin value. Parameters: *
pin - Pin variable. * Return boolean true when pin is high and false when pin is low. * bool pin_get_debounced_value(pin pin)
Reads pin value through the switch debounce filter. Filtering takes at least 8 ms and may last up to 100 ms, depending on when the bouncing ends. If the bouncing does not end,
false is returned. Function uses software delay. Parameters: * pin - Pin variable. * Return pin boolean value - true when pin is high and false when pin is low or undetermined. === Example === Example of getting and setting a pin's value. Pin PC0 value is inverted and attached to pin PC3. #include pin output_pin = PIN(C, 3); pin input_pin = PIN(C, 0); int main(void) { bool value; Configuring pin as an output pin

pin_setup_output(output_pin);
// Configuring pin as an input pin with pull-up
pin_setup_input_with_pullup(input_pin);
// Endless loop
while (true)
{
	// Getting an input pin value
	value = pin_get_value(input_pin);
	// Setting an output pin value
	pin_set_to(output_pin, !value);
}

}

led_on, led_off, button_read commands example

#include

Homelab buttons and LEDs are predefined in the library int main(void) { Set LED pin as output

pin_setup_output(led_green);
// Set Button S1 pin as input
pin_setup_input(S1);
// Endless loop
while (true)
{
	// If button is pressed, turn on LED, if not pressed, turn LED off.
	if(button_read(S1) == true)
		led_on(led_green);
	else
		led_off(led_green);
}

}

Analog to Digital Converter

This library provides functions to use AVR analog to digital converter. All the conversion functions in library are blocking, which means the processor waits as long as it takes to get the results. The conversion time depends on the ADC clock.

Data Types

  • adc_reference
    ADC reference voltage enumeration data type. Options:
    • ADC_REF_AREF - Reference voltage from the AREF pin.
    • ADC_REF_AVCC - Reference voltage from the AVCC pin.
    • ADC_REF_2V56 - Internal 2,56 V reference voltage.
  • adc_prescale
    ADC clock prescaler enumration data type. It determines the division factor of system clock. Options:
    • ADC_PRESCALE_2 - Division factor 2.
    • ADC_PRESCALE_4 - Division factor 4.
    • ADC_PRESCALE_8 - Division factor 8.
    • ADC_PRESCALE_16 - Division factor 16.
    • ADC_PRESCALE_32 - Division factor 32.
    • ADC_PRESCALE_64 - Division factor 64.
    • ADC_PRESCALE_128 - Division factor 128.

Functions

  • void adc_init(adc_reference reference, adc_prescale prescale)

Initializes ADC. Parameters:

  • reference - Reference voltage selection.
  • prescale - Clock prescaler selection.
  • unsigned short adc_get_value(unsigned char channel)

Converts specified ADC channel analog value to digital. Function is blocking. Parameter:

  • channel - ADC channel number (0 to 7).
  • Return 10-bit digital value.
  • unsigned short adc_get_average_value(unsigned char channel, unsigned char num_samples)

Converts specified ADC channel analog value to digital desired number of times and calculates the average. Function is blocking. Parameters:

  • channel - ADC channel number (0 to 7).
  • num_samples - Number of samples for calculation (1 to 64).
  • Return 10-bit digital value.

Example

For example ADC is initialized and two analog channel values are converted to digital. Value of channel 0 is assigned to variable x and averaged value of channel 1 to variable y.

#include

int main(void) {

unsigned short x, y;
// Initializing ADC. Reference voltage from AVCC.
// Clock is 8 times slower than system clock.
adc_init(ADC_REF_AVCC, ADC_PRESCALE_8);
// Converting channel 0 value.
x = adc_get_value(0);
// Converting and averaging channel 1 value.
y = adc_get_average_value(1, 10);

}

Serial Interface

This library provides AVR asynchronous serial interface usage functions.

Data Types

  • usart
    Data type to hold USART inteface control, status and data register addresses. usart typed variables should be initialized at the beginning of the program code. For initializations, there is a macro-functions USART, whose only parameter is the index of interface (0 or 1).
  • usart_databits
    Data bits count enumeration data type. Options:
    • USART_DATABITS_5 - 5 data bits.
    • USART_DATABITS_6 - 6 data bits.
    • USART_DATABITS_7 - 7 data bits.
    • USART_DATABITS_8 - 8 data bits.
    • USART_DATABITS_9 - 9 data bits.
  • usart_stopbits
    Stop bits count enumeration data type. Options:
    • USART_STOPBITS_ONE - One stop bit.
    • USART_STOPBITS_TWO - Two stop bits.
  • usart_parity
    Parity mode enumeration data type. Options:
    • USART_PARITY_NONE - Disabled.
    • USART_PARITY_EVEN - Even parity.
    • USART_PARITY_ODD - Odd parity.

Functions

  • USART_BAUDRATE_ASYNC(baud)

Macro function to calculate USART baud rate register value in asynchronous mode. Parameters:

  • baud - Desired baud rate.
  • Returns baud rate register value.
  • void usart_init_async(usart port, usart_databits data_bits, usart_stopbits stop_bits, usart_parity parity, usart_baudrate baudrate)

Initializes asynchronous USART. Parameters:

  • port - USART interface variable.
  • data_bits - Data bits.
  • stop_bits - Stop bits.
  • parity - Parity mode.
  • baudrate - Baud rate register value (can be calculated with USART_BAUDRATE_ASYNC macro function).
  • void usart_send_char(usart port, char symbol)

Blocking character transmission. Functions wait until transmit buffer empties before writing a character to the buffer. Parameters:

  • port - USART interface variable.
  • symbol - Character to be sent.
  • void usart_send_string(usart port, char *text)

Blocking string transmission. Parameters:

  • port - USART interface variable.
  • text - Pointer to strin (char array). String has to end with null character.
  • bool usart_has_data(usart port)

Checks for data in receive buffer. Parameters:

  • port - USART interface variable.
  • Returns true when there is a character in receive buffer, and false when not.
  • char usart_read_char(usart port)

Reads a character from receive buffer. Before reading user must check if there actually is a received character. Parameters:

  • port - USART interface variable.
  • Returns character.
  • bool usart_try_read_char(usart port, char *symbol)

Reads a character from receive buffer if there is any. Parameters:

  • port - USART interface variable.
  • symbol - Pointer to character variable. If there is a character in receive buffer, it is written to the pointed variable.
  • Returns true when there was a character in receive buffer, and false when not.

Example

USART interface is configured to use 8 data bits, one stop bit, 9600 bps baud rate and no parity mode. Program sends a string, waits until some character is received and then reads it out.

#include

Use USART interface 0. usart port = USART(0); int main(void) { char c; Interface initialization.

usart_init_async(port,
	USART_DATABITS_8,
	USART_STOPBITS_ONE,
	USART_PARITY_NONE,
	USART_BAUDRATE_ASYNC(9600));
// String sending.
usart_send_string(port, "Hello\n");
// Waiting for incoming data.
while (!usart_has_data(port)) {}
// Read out the received character.
c = usart_read_char(port);

}

Timers

This library covers a large part of the functionality of ATmega128 timers. There are data types and functions which make usage of timers easier. Unfortunately, because of the complexity of AVR timers, there are no common functions to use different timers. Each of the timers has functions which start with the prefix of „timer“ and its index.

Data types

  • timer0_prescale
    Timer 0 prescaler enumeration data type. Options:
    • TIMER0_NO_PRESCALE - No prescaler (no division).
    • TIMER0_PRESCALE_8 - Clk / 8.
    • TIMER0_PRESCALE_32 - Clk / 32.
    • TIMER0_PRESCALE_64 - Clk / 64.
    • TIMER0_PRESCALE_128 - Clk / 128.
    • TIMER0_PRESCALE_256 - Clk / 256.
    • TIMER0_PRESCALE_1024 - Clk / 1024.
  • timer2_prescale
    Timer 2 prescaler enumeration data type. Options:
    • TIMER2_NO_PRESCALE - No prescaler (no division).
    • TIMER2_PRESCALE_8 - Clk / 8.
    • TIMER2_PRESCALE_64 - Clk / 64.
    • TIMER2_PRESCALE_256 - Clk / 256.
    • TIMER2_PRESCALE_1024 - Clk / 1024.
    • TIMER2_PRESCALE_T2_FALLING - Clock on pin T2 falling edge.
    • TIMER2_PRESCALE_T2_RISING - Clock on pin T2 rising edge.
  • timer1_prescale
  • timer3_prescale
    Timer 1/3 prescaler enumeration data type. Options („n“ means 1 or 3):
    • TIMERn_NO_PRESCALE - No prescaler (no division).
    • TIMERn_PRESCALE_8 - Clk / 8.
    • TIMERn_PRESCALE_64 - Clk / 64.
    • TIMERn_PRESCALE_256 - Clk / 256.
    • TIMERn_PRESCALE_1024 - Clk / 1024.
    • TIMERn_PRESCALE_Tn_FALLING - Clock on pin Tn falling edge.
    • TIMERn_PRESCALE_Tn_RISING - Clock on pin Tn rising edge.
  • timer1_ctc_top
  • timer3_ctc_top
    Timer 1/3 CTC mode top value enumeration data type. Options („n“ means 1 or 3):
    • TIMERn_CTC_TOP_OCRA - Top value from timer 1/3 output compare register A.
    • TIMERn_CTC_TOP_ICR - Top value from timer 1/3 input capture register.
  • timer1_fast_pwm_top
  • timer3_fast_pwm_top
    Timer 1/3 fast PWM mode top value enumeration data type. Options („n“ means 1 or 3):
    • TIMERn_FAST_PWM_TOP_256 - Top value 255.
    • TIMERn_FAST_PWM_TOP_512 - Top value 511.
    • TIMERn_FAST_PWM_TOP_1024 - Top value 1023.
    • TIMERn_FAST_PWM_TOP_ICR - Top value from timer 1/3 input capture register.
    • TIMERn_PAST_PWM_TOP_OCRA - Top value from timer 1/3 output compare register A.
  • timer1_fast_pwm_output_mode
  • timer1_fast_pwm_output_mode
    Timer 1/3 fast PWM mode outputs configuration enumeration data type. Options („n“ means 1 or 3):
    • TIMERn_FAST_PWM_OUTPUT_DISABLE - No output.
    • TIMERn_FAST_PWM_OUTPUT_TOGGLE_ON_MATCH - Output toggles on compare match.
    • TIMERn_FAST_PWM_OUTPUT_CLEAR_ON_MATCH - Output clears on compare match.
    • TIMERn_FAST_PWM_OUTPUT_SET_ON_MATCH - Output sets on compare match.

Functions

  • void timer0_init_normal(timer0_prescale prescale)

Initializes timer 0 in normal mode. In this mode the timer counts from 0 to 255 (including). Overflow interrupt can be used. Parameters:

  • prescale - Prescaler.
  • void timer2_init_normal(timer2_prescale prescale)

Initializes timer 2 in normal mode. In this mode timer counts from 0 to 255 (including). Overflow interrupt can be used. Parameters:

  • prescale - Prescaler.
  • void timer0_stop()
  • void timer2_stop()

Stops timer 0/2.

  • unsigned char timer0_get_value(void)
  • unsigned char timer2_get_value(void)

Returns timer 0/2 current value. Parameters:

  • Return 8-bit timer value.
  • void timer0_set_value(unsigned char value)
  • void timer2_set_value(unsigned char value)

Sets timer 0/2 value. Parameters:

  • value - New 8-bit timer value.
  • void timer0_overflow_interrupt_enable(bool enable)
  • void timer2_overflow_interrupt_enable(bool enable)

Enables or disables timer 0/2 overflow interrupt. The name of the interrupt vector is „TIMERn_OVF_vect“ where „n“ represents 0 or 2. Parameters:

  • enable - true to enable interrupt, false to disable.
  • bool timer0_overflow_flag_is_set(void)
  • bool timer2_overflow_flag_is_set(void)

Checks timer 0/2 overflow flag. Parameters:

  • Returns true when overflow has happened, false when not.
  • void timer0_overflow_flag_clear(void)
  • void timer2_overflow_flag_clear(void)

Resets timer 0/2 overflow flag.

  • void timer1_init_normal(timer1_prescale prescale)
  • void timer3_init_normal(timer3_prescale prescale)

Initializes timer 1/3 in normal mode. In this mode timer counts from 0 to 65535 (including). Overflow interrupt can be used. Parameters:

  • prescale - Prescaler.
  • void timer1_init_ctc(timer1_prescale prescale, timer1_ctc_top top)
  • void timer3_init_ctc(timer3_prescale prescale, timer3_ctc_top top)

Initializes timer 1/3 in CTC (Clear Timer on Compare Match) mode. In this mode timer counts to specified top value. Overflow interrupt can be used. Parameters:

  • prescale - Prescaler.
  • top - Timer top value selection. Actual value must be specified with register selected as a top value holder.
  • void timer1_init_fast_pwm(timer1_prescale prescale, timer1_fast_pwm_top top, timer1_fast_pwm_output_mode output_a, timer1_fast_pwm_output_mode output_b, timer1_fast_pwm_output_mode output_c)
  • void timer3_init_fast_pwm(timer3_prescale prescale, timer3_fast_pwm_top top, timer3_fast_pwm_output_mode output_a, timer3_fast_pwm_output_mode output_b, timer3_fast_pwm_output_mode output_c)

Initializises timer 1/3 in fast PWM mode. In this mode timer counts to a specified value, which also determines the period of the PWM signal. Timer 1/3 has three 3 output compare units (A, B and C) to generate PWM signals. Overflow and compare match interrupts can be used. Parameters:

  • prescale - Prescaler.
  • top - Timer top value selection. Actual value must be specified with register selected as a top value holder.
  • output_a - Output compare unit A pin configuration.
  • output_b - Output compare unit B pin configuration.
  • output_c - Output compare unit C pin configuration.
  • void timer1_stop()
  • void timer3_stop()

Stops timer 1/3.

  • unsigned char timer1_get_value(void)
  • unsigned char timer3_get_value(void)

Returns timer 1/3 current value. Parameters:

  • Returns 16-bit timer value.
  • void timer1_set_value(unsigned char value)
  • void timer3_set_value(unsigned char value)

Sets timer 0/2 value. Parameters:

  • value - New 16-bit timer value.
  • unsigned short timer1_get_compare_match_unitA_value(void)
  • unsigned short timer1_get_compare_match_unitB_value(void)
  • unsigned short timer1_get_compare_match_unitC_value(void)
  • unsigned short timer3_get_compare_match_unitA_value(void)
  • unsigned short timer3_get_compare_match_unitB_value(void)
  • unsigned short timer3_get_compare_match_unitC_value(void)

Returns timer 1/3 output compare unit A/B/C compare match register value. Parameters:

  • Returns 16-bit compare match register value.
  • void timer1_set_compare_match_unitA_value(unsigned short value)
  • void timer1_set_compare_match_unitB_value(unsigned short value)
  • void timer1_set_compare_match_unitC_value(unsigned short value)
  • void timer3_set_compare_match_unitA_value(unsigned short value)
  • void timer3_set_compare_match_unitB_value(unsigned short value)
  • void timer3_set_compare_match_unitC_value(unsigned short value)

Sets timer 1/3 output compare unit A/B/C compare match register value. Parameters:

  • value - New 16-bit compare match register value.
  • unsigned short timer1_get_input_capture_value(void)
  • unsigned short timer3_get_input_capture_value(void)

Returns timer 1/3 input capture register value. Parameters:

  • Returns 16-bit input capture register value.
  • void timer1_set_input_capture_value(unsigned short value)
  • void timer3_set_input_capture_value(unsigned short value)

Sets timer 1/3 input capture register value. Parameters:

  • value - New 16-bit input capture register value.
  • void timer1_overflow_interrupt_enable(bool enable)
  • void timer3_overflow_interrupt_enable(bool enable)

Enables or disables timer 1/3 overflow interrupt. The name of the interrupt vector is „TIMERn_OVF_vect“ where „n“ represents 1 või 3. Parameters:

  • enable - true to enable interrupt, false to disable.
  • void timer1_compare_match_unitA_interrupt_enable(bool enable)
  • void timer1_compare_match_unitB_interrupt_enable(bool enable)
  • void timer1_compare_match_unitC_interrupt_enable(bool enable)
  • void timer3_compare_match_unitA_interrupt_enable(bool enable)
  • void timer3_compare_match_unitB_interrupt_enable(bool enable)
  • void timer3_compare_match_unitC_interrupt_enable(bool enable)

Enables or disables timer 1/3 output compare unit A/B/C compare match interrupt. The name of the interrupt vector is „TIMERn_COMPx_vect“ where „n“ represents 1 or 3 and „x“ represents A, B or C. Parameters:

  • enable - true to enable interrupt, false to disable.
  • void timer1_input_capture_interrupt_enable(bool enable)
  • void timer3_input_capture_interrupt_enable(bool enable)

Enables or disables timer 1/3 input capture interrupt. The name of the interrupt vector is „TIMERn_CAPT_vect“, where „n“ represents 1 or 3. Parameters:

  • enable - true to enable interrupt, false to disable.
  • bool timer1_overflow_flag_is_set(void)
  • bool timer3_overflow_flag_is_set(void)

Checks timer 1/3 overflow flag. Parameters:

  • Returns true when overflow has happened, false when not.
  • bool timer1_input_capture_flag_is_set(void)
  • bool timer3_input_capture_flag_is_set(void)

Checks timer 1/3 input capture flag. Parameters:

  • Returns true when input capture has done, false when not.
  • void timer1_overflow_flag_clear(void)
  • void timer3_overflow_flag_clear(void)

Resets timer 1/3 overflow flag.

  • void timer1_input_capture_flag_clear(void)
  • void timer3_input_capture_flag_clear(void)

Resets timer 1/3 input capture flag.

Example

In the following program timer 0 is started in normal mode with overflow interrupt.

#include #include

Overflow interrupt program. ISR(TIMER0_OVF_vect) { } int main(void) { Initializing of timer 0 in normal mode.

timer0_init_normal(TIMER0_PRESCALE_32);
// Enabling timer 0 overflow interrupt.
timer0_overflow_interrupt_enable(true);
// Global interrupts enabling.
sei();

}

/home/www/roboticlab/homelab_data/pages/en/software/homelab/library/timer_xmega.txt— MISSING PAGE —

Delay

This part of library contains functions to generate delays in the program with software algorithms or with hardware timers. Delays do not block interrupts, therefore interrupts interfere with software delays. Delay functions are not pre-compiled to be compatible with different clock frequencies.

Functions

  • void sw_delay_ms(unsigned short count)

Software delay in milliseconds. Function expects the usage of some compiler optimization mode. Parameters:

  • count - Delay time in milliseconds. 0 to 65535 ms.
  • void sw_delay_us(unsigned short count)

Software delay in microseconds. Function expects the usage of some compiler optimization mode. Parameters:

  • count - Delay time in microseconds. 0 to 65535 μs.
  • void hw_delay_ms(unsigned short count) \\'

Hardware timer based delay in milliseconds. Functions use ATmega128 8-bit timer 0. Depending of the clock frequency, up to several milliseconds delay error may occur. Parameters:

  • count - Delay time in milliseconds. 0 to 65535 ms.

Examples

Demonstration of both types of delays.

#include

int main(void) {

// Software base delay of 100 ms.
sw_delay_ms(100);

// Hardware timer based delay of 100 ms.
hw_delay_ms(100);

}

/home/www/roboticlab/homelab_data/pages/en/software/homelab/library/buzzer.txt— MISSING PAGE —

7-segment LED Display

Related to: [HW] User Interface Module

This library is intended to use a 7-segment LED display on the HomeLab Digital i/o module board. Numbers from 0 to 9 can be displayed with the library.

Functions

  • void segment_display_init(void)

Configures display driver control pins.

  • void segment_display_write(unsigned char digit)

Displayes a digit on display. Parameters:

  • digit - Number value from 0 to 9. Any other case E like „error“ is displayed.

Example

Number 5 is showed on LED display.

#include

int main(void) {

// Display initialization.
segment_display_init();
// Digit displaying.
segment_display_write(5);

}

Alphanumeric LCD

Related to: [HW] User Interface Module

This library contains functions to use the HomeLab alphanumeric LCD.

Data Types

  • lcd_alpha_mode
    LCD configuration enumeration data type. Options:
    • LCD_ALPHA_DISP_OFF - Display off.
    • LCD_ALPHA_DISP_ON - Display on with invisible cursor.
    • LCD_ALPHA_DISP_ON_CURSOR - Display on with cursor.
    • LCD_ALPHA_DISP_ON_CURSOR_BLINK - Display on with blinking cursor.

Functions

  • void lcd_alpha_init(lcd_alpha_mode disp_attr)

Initializes LCD. Parameters:

  • disp_attr - Display configuration.
  • void lcd_alpha_clear(void)

Clears the whole display. Cursor is moved to the beginning of the first line.

  • void lcd_alpha_clear_line(unsigned char line)

Clears a line on display. Cursor is moved to the beginning of cleared line. Parameters:

  • line - Line number. 0 or 1.
  • void lcd_alpha_home(void)

Moves cursor to the beginning of the first line.

  • void lcd_alpha_goto_xy(unsigned char x, unsigned char y)

Moves cursor to the desired position. Parameters.

  • x - X coordinate (column number). 0 to 15.
  • y - Y coordinate (line number). 0 to 1.
  • void lcd_alpha_write_char(char c)

Writes a character to the cursor position. Parameters:

  • c - ASCII character.
  • void lcd_alpha_write_string(const char *s)

Writes a string to the display starting from the position of the cursor. Parameters:

  • s - Pointer to string (char array).
  • void lcd_alpha_write_string_p(const char *progmem_s)

Writes a string from program memory to the display starting from the position of the cursor. Parameters

  • progmem_s - Pointer to string in program memory.

Example

Demonstration of how to use alphanumeric LCD to display text.

#include

int main(void) {

// LCD initialization.
lcd_alpha_init(LCD_ALPHA_DISP_ON);
// Display clearing.
lcd_alpha_clear();
// Cursor to the beginning of second line.
lcd_alpha_goto_xy(0, 1);	
// Text displaying.
lcd_alpha_write_string("Hello");

}

Graphic LCD

Related to: [HW] User Interface Module

This library contains functions to use the HomeLab graphical LCD. Although the LCD is capable of displaying graphical images, no such functions are implemented in the library. The LCD is used as a 14 x 6 character alphanumeric display.

Functions

  • void lcd_gfx_init(void)

Intializes LCD.

  • void lcd_gfx_backlight(bool set)

Switch LCD backlight on or off. Parameters:

  • set - true when backlight on, false when off.
  • void lcd_gfx_clear(void)

Clears a whole display.

  • void lcd_gfx_clear_line(unsigned char line)

Clears a single text line. Parameters:

  • line - Line number. 0 to 5.
  • void lcd_gfx_goto_char_xy(unsigned char x, unsigned char y)

Selects a position to write text to. Parameters:

  • x - X coordinate. 0 to 13.
  • y - Y coordinate. 0 to 5.
  • void lcd_gfx_write_char(char c)

Writes a character to the pre-defined position. Parameters:

  • c - ASCII character.
  • void lcd_gfx_write_string(char *s)

Writes a string to the display starting from the pre-defined position. Parameters:

  • s - Pointer to string (char array).

Example

Demonstration of using a graphical LCD.

#include

int main(void) {

// LCD initialization.
lcd_gfx_init();
// Display clearing.
lcd_gfx_clear();
// Cursor to the middle of the screen.
lcd_gfx_goto_char_xy(5, 2);
// Displaying a text.
lcd_gfx_write_string("Hello");

}

Motors

Related to: [HW] Motor Module

This library contains functions to control different HomeLab motors. There are functions for DC, stepper and servo motors.

Data Types

  • prescale
    PWM clock prescaler enumration data type. It determines the division factor of system clock. It is recommended to use the first two division factors. Options:
    • TIMER2_NO_PRESCALE - Division factor not used.
    • TIMER2_PRESCALE_8 - Division factor 8.
    • TIMER2_PRESCALE_64 - Division factor 64.
    • TIMER2_PRESCALE_256 - Division factor 256.
    • TIMER2_PRESCALE_1024 - Division factor 1024.

Functions

  • void dcmotor_init(unsigned char index)

Initializes one of the DC motor controllers. Parameters:

  • index - Index of motor controller. 0 to 3.
  • void dcmotor_drive(unsigned char index, signed char direction)

Drives one of the DC motor controllers. Parameters:

  • index - Index of motor controller. 0 to 3.
  • direction - Motor polarity. -1, 0 or +1. In case of 0 motor is stopped, otherwise it turns in given direction.
  • void dcmotor_drive_pwm_init(unsigned char index, timer2_prescale prescaler)
    Initializes one of the DC motor controllers for speed control. In addition, you can set the appropriate prescaler, depending on the frequency of the PWM's you need. Parameters:
    • index - Index of motor controller. 0 to 3.
    • prescaler - Clock prescaler selection. Interruptions can occur very quickly upset the program of work. For example, when the UH sensor is used, it is necessary to set the prescaler TIMER2_PRESCALE_8.
  • void dcmotor_drive_pwm(unsigned char index, signed char direction, unsigned char speed)

Drives one of the DC motor controllers. Motor rotates in a predetermined direction and speed. Parameters:

  • index - Index of motor controller. 0 to 3.
  • direction - Motor polarity. -1 or +1.
  • speed - Motor speed. 0 to 255. 0 the engine is stopped and the 255 is the maximum possible speed.
  • void unipolar_init(unsigned char index)

Initializes one of the unipolar stepper motor controllers. Parameters:

  • index - Index of motor controller. 0 or 1.
  • void unipolar_halfstep(unsigned char index, signed char direction, unsigned short num_steps, unsigned char speed)

Unipolar stepper motor half-stepping command. Functions is blocking as it is fulfilled as long as steps are done. Parameters:

  • index - Index of motor controller. 0 or 1.
  • direction - Directions of rotation. -1 or +1.
  • num_steps - Count of half-steps.
  • speed - Time of a single step in milliseconds.
  • void bipolar_init(void)

Initializes bipolar stepper motor controller.

  • void bipolar_halfstep(signed char direction, unsigned short num_steps, unsigned char speed)

Bipolar stepper motor half-stepping command. Functions is blocking as it is fulfilled as long as steps are done. Parameters:

  • direction - Directions of rotation. -1 or +1.
  • num_steps - Count of half-steps.
  • speed - Time of a single step in milliseconds.
  • void servomotor_init(unsigned char index)

Initializes one of a servo motor PWM signal generations units in ATmega128 timer 1. PWM signal is 50 hz with high period of 1.5 ms ± 0.5 ms. Parameters:

  • index - Index of servo motor. 0 or 1.
  • void servomotor_position(unsigned char index, signed short position)

Servo motor pulse width control command. If positioning servo motor is driven, its position is altered, if rotating one, its rotation speed is altered. Parameters:

  • index - Index of servo motor. 0 or 1.
  • position - Position or rotation speed. -100 to +100. 0 corresponds to stop.

Example

The following program demonstrates the usage of DC, stepper and servo motors.

#include

int main(void) {

// DC motors initialization.
dcmotor_init(0);
dcmotor_init(1);
// Bipolar stepper initialization.
bipolar_init();
// Servo motors initialization.
servomotor_init(0);
servomotor_init(1);
// One DC motors drives forward, another in backward direction.
dcmotor_drive(0, -1);
dcmotor_drive(1, +1);
// Rotating the stepper motor 100 steps in one direction
// and then back with twice the speed.
bipolar_halfstep(1, 100, 50);
bipolar_halfstep(-1, 100, 25);
// Rotating servo motors in opposite directions.
servomotor_position(0, -100);
servomotor_position(1, +100);

}

This example demonstrates the speed adjustments of a DC motor.

#include

int main(void) {

      unsigned char speed = 0;

// DC motors initialization
	dcmotor_drive_pwm_init(0, TIMER2_NO_PRESCALE);
	while(1)
	{   	
	speed = 100;
	// DC motors drives predefined speed and direction.
	dcmotor_drive_pwm(0, 1, speed);			      
	}

}

Encoders

Related to modules: [HW] Motor Module

This library includes usage functions of Homelab's encoders.

Functions

  • void encoder_init(unsigned char index)

configures selected encoder and the input pins. Parameters:

  • index - Number of the encoder. Value 0 to 1.
  • void encoder_reset_pulses(unsigned char index)

Resets and starts counting the selected encoder. Parameters:

  • index - Number of the encoder. Value 0 to 1.
  • unsigned short encoder_get_pulses(unsigned char index)

Request of counted encoder impulses. Parameters:

  • index - Number of the encoder. Value 0 to 1.
  • Returns the number of pulses

 

Example

Example of using the Homelab's encoders. The number of pulses is displayed on LCD. #include #include #include #include #include #include

Button pin pin button2 = PIN(C, 1); int main(void) { unsigned short pulses = 0; char text[16]; Sets buttons

pin_setup_input_with_pullup(button2);
// Initialization of encoder 
encoder_init(0);
// Reset and start counting
encoder_reset_pulses(0);
// LCD display initialization
lcd_gfx_init();

Clear display lcd_gfx_clear(); Turning back light ON

lcd_gfx_backlight(true);	

Displaying source code name lcd_gfx_goto_char_xy(3, 1); lcd_gfx_write_string(„Encoder“); while (true) { pulses = encoder_get_pulses(0); Generating a string

	sprintf(text, "Pulsse: %d",pulses);

lcd_gfx_goto_char_xy(0, 3);

	lcd_gfx_write_string(text);
	// Button 2 is pressed
    if(!pin_get_debounced_value(button2))
	{
		// Reset and start counting
		encoder_reset_pulses(0);
		// Make a beep
		buzzer_sound (60, 100);
		// Erase previous number
		lcd_gfx_write_string("    ");
	} 
	 
	// Software delay for 10 ms 
	sw_delay_ms(10);
}

}

Sensors

Related to: [HW] Sensors Module

This library contains functions to use different sensors in the HomeLab kit.

Data Types

  • ir_distance_sensor

Infrared distance sensor distance calculation parameters structure. Formula for distance calculation is a / (ADC + b) - k. Structure members:

  • a - Dividend.
  • b - Non-linear constant.
  • k - Linearizing constant.

Constants

  • ir_distance_sensor GP2Y0A21YK

Sharp GP2Y0A21YK distance calculation formula parameters.

Functions

  • signed short thermistor_calculate_celsius(unsigned short adc_value)

Calculates thermistor temperature in Celsius degrees from ADC conversion result. Functions use pre-calculated conversion table. Parameters:

  • adc_value - ADC conversion result (10-bit with +5 V reference voltage)..
  • Returns temperature in Celsius degrees in the -20 to 100 degrees limit.
  • signed short ir_distance_calculate_cm(ir_distance_sensor sensor, unsigned short adc_value)

Calculates distance from ADC result received from IR distance sensor voltage. Parameters:

  • sensor - Distance sensor calculation parameters.
  • adc_value - ADC conversion result (10-bit with +5 V reference voltage).
  • Returns distance in centimeters or -1 if it cannot be calculated.
  • unsigned short ultrasonic_measure_srf04(pin trigger, pin echo)

Measures distance with ultrasonic distance sensor SRF04. Function generates a trigger pulse on one pin and measures the time of echo pulse on another pin. Distance is calculated from the time. Function expects a 14.7456 MHz clock frequency. Measuring may take up to 36 ms. Parameters:

  • trigger - Trigger pin variable.
  • echo - Echo pin variable.
  • Returns distance in centimeters or 0 when measuring failed.
  • unsigned short ultrasonic_measure_srf05(pin trigger_echo)

Measures distance with ultrasonic distance sensor SRF05 in one wire regime. Function generates a trigger pulse on the pin and measures the time of echo pulse on the same pin. Distance is calculated from the time. Function expects a 14.7456 MHz clock frequency. Measuring may take up to 36 ms. Parameters:

  • trigger_echo - Trigger/Echo combined pin variable.
  • Returns distance in centimeters or 0 when measuring failed.

Example

The following program demonstrates usage of IR and ultrasonic distance sensor SRF05.

#include

Ultrasonic distance sensor control pins. pin pin_triggerecho = PIN(G, 0); int main(void) { unsigned short adc_value = 400; random ADC result.

signed short distance;
// Distance calculation from IR distance sensor ADC result.
distance = ir_distance_calculate_cm(GP2Y0A21YK, adc_value);
// Measuring with ultrasonic distance sensor.
distance = ultrasonic_measure_srf05(pin_triggerecho);

}

Ethernet

Necessary knowledge: [HW] Controller module

The following part of library contains HomeLab Ethernet functions.

Constants

  • static uint8_t mymac[6] = {0x54,0x55,0x58,0x10,0x00,0x24} - controller MAC address (you can choose a random address, but it is important to be unique in the network).
  • static uint8_t myip[4] = {192,168,1,100} - IP address corresponding to LAN, you must choose different last digit, if it is already present in the network.
  • static uint8_t buf[BUFFER_SIZE+1] - size of data buffer (usually 600+1 B).

Functions

  • void ethernet_standby(void)

Brings Ethernet controller into sleep mode (low energy consumption).

  • void ethernet_init(uint8_t *mac, uint8_t *ip)

Ethernet controller initial setup with MAC and IP addresses.

  Parameters:
  * //*mac// - MAC address array.
  * //*ip// - IP address array.
  • uint16_t ethernet_get_packet (uint16_t maxlen, uint8_t* packet)

Polls network until it receives packet addressed to it and containing data.

  Parameters:
  * //maxlen// - maximum allowed data buffer size.
  * //*buffer// - array where to save received data for further operations.
  * If the packet has arrived, returns the length of the received packet in bytes and in opposite case returns 0.
  • uint16_t ethernet_analyse_packet(uint8_t *buf,uint16_t plen)

Analyzes if received packet contains info about URL. Will respond to ping if needed.

  Parameters:
  * //*buf// - data array to analyze.
  * //plen// - length of received packet in bytes.
  * Tagastab URL-i esimese tähemärgi aadressi. Kui URL on tühi, siis tagastab 0.
  * Returns the address of the first char in URL. If URL is empty, it will return 0.
  • uint16_t ethernet_load_data (uint8_t *buf,uint16_t pos, const prog_char *progmem_s)

Loads HTML-code for displaying webpage from controller program memory into TCP send buffer.

  Parameters:
  * //*buf// - data arrya to send using TCP.
  * //pos// - data end address in buffer which must be maintained if data is loaded in queue. The first address is 0.
  * //*progmem_s// - string name that is saved into program memory and from where data is loaded into send array.
  * Retruns end address of data array which can be input as a parameter for loading next HTML-code.
  • void ethernet_print_webpage (uint8_t *buf,uint16_t dlen)

Dislays webpage according to preloaded HTML-code.

  Parameters:
  * //*buf// - Data array where HTLM is preloaded.
  * //dplen// - End address of data in buffer to be displayed as HTML-code.

 

Example

#include #include #include

Function for compiling webpage uint16_t ethernet_load_webpage(uint8_t on_off); MAC and IP must be unique in network, same addresses in two devices are not allowed. Random MAC address (usually no need to change it) static uint8_t mymac[6] = {0x54,0x55,0x58,0x10,0x00,0x24};

IP according to LAN (you need to choose the last number) static uint8_t myip[4] = {192,168,1,100}; length of data array static uint16_t gPlen;

Data buffer size #define BUFFER_SIZE 600 static uint8_t buf[BUFFER_SIZE+1]; LED PB7 variable pin debug_led = PIN(B, 7);

int main(void) {

uint16_t pktlen;
char *str;  
// LED PB7 is output
pin_setup_output(debug_led);

// Etherneti initialization with given addresses
ethernet_init(mymac, myip);			
       
      while(1)
{
// Receive packets until it receives addressed to him with data
  	pktlen=ethernet_get_packet(BUFFER_SIZE, buf);
      // Performs packet preconditioning and answer to "ping" packet. 
      // Returns packet URL.
      gPlen=ethernet_analyse_packet(buf,pktlen);
// If URL contains info, start analyzing it
      if (gPlen!=0)
{               
          // Load URL address part into "str". 
          // The first 4 digits are IP address numbers.
          str = (char *)&(buf[gPlen+4]);
		
		// Find string "/1" from URL              
		if (strncmp("/1",str,2)==0)
		{
                        // Load webpage
			gPlen = ethernet_load_webpage(0);
			// LED on
			pin_clear(debug_led);		
            
                 }
		// At next, find string "/0" from URL
		else if (strncmp("/0",str,2)==0)
		{
                        // Load webpage
			gPlen = ethernet_load_webpage(1);
			// LED on
			pin_set(debug_led);
           
                 }
		// In other cases load webpage according to LED condition
                else 
		{	           
                   gPlen=ethernet_load_webpage(pin_get_value(debug_led));
                }                                    
		
		// Display preloaded webpage                
                      ethernet_print_webpage (buf,gPlen);    			            
	}
  }
  return (0);

}

Webpage will be loaded by writing data into TCP send buffer uint16_t ethernet_load_webpage(uint8_t on_off) { uint16_t plen=0; Load HTML-code into buffer to send it

// Those large strings are saved into program memory using PSTR macro,
// to save SRAM
// Load webpage header
plen=ethernet_load_data(buf,0,PSTR
("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\nPragma: no-cache\r\n\r\n"));
  
plen=ethernet_load_data(buf,plen,PSTR("Homelab PB7 LED: "));

  // if LED is off, display it
  if (on_off)
  {
    plen=ethernet_load_data(buf,plen,PSTR(" OFF"));
  }
  // if LED is on
  else
  {
    plen=ethernet_load_data(buf,plen,PSTR(" ON"));
  }
  // Lae "Refresh" nupp
  plen=ethernet_load_data(buf,plen,PSTR
  (" [refresh status]\nSwitch on"));
	 
  }
  else
  {
       plen=ethernet_load_data(buf,plen,PSTR("/0\">Switch off"));
	 
  } 
   
  // Return the end address of data in buffer
  return(plen);

}

SD-card

Necessary knowledge: [HW] Controller module

This section of library contains functions for using HomeLab SD-card.

Data types

  • static FATFS FATFS_Obj - FATFS_Obj is FATFS data structure instance. Consists of drive identificators.
  • FIL fil_obj - File system data structure where to store file identificators.
  • DSTATUS - Return codes for drive related functions.
    • RES_OK - (0) Procedure successful.
    • RES_ERROR - (1) R/W error.
    • RES_WRPRT - (2) Write protected.
    • RES_NOTRDY - (3) Drive not ready.
    • RES_PARERR - (4) Some parameters are false.
  • FRESULT - Most important codes that are returned from file related functions.
    • FR_OK - (0) Procedure successful.
    • FR_DISK_ERR - (1) Drive I/O layer error
    • FR_INT_ERR - (2) General drive error
    • FR_NOT_READY - (3) Drive not ready for procedure.
    • FR_NO_FILE - (4) File not found.
    • FR_NO_PATH - (5) Address not found.
    • FR_INVALID_NAME - (6) Wrong file name format.
    • FR_DENIED - (7) Drive is full.
    • FR_EXIST - (8) Access is denied.
    • FR_INVALID_OBJECT - (9) File or folder object error.
    • FR_WRITE_PROTECTED - (10) Drive is write protected.
    • FR_INVALID_DRIVE - (11) Drive number is false.
    • FR_NO_FILESYSTEM - (13) Supported FAT file system not found.
    • FR_TIMEOUT - (15) Connection with drive failed.
    • FR_INVALID_PARAMETER - (19) Some parameters are false.
  • ModeFlags - Possible modes to open files.
    • FA_READ - File open in read mode.
    • FA_WRITE - File open in write mode.
    • FA_OPEN_EXISTING - Opens file. If it does not exists then returns error code.
    • FA_OPEN_ALWAYS - Opens file. If it does not exists then creates it.
    • FA_CREATE_NEW - Creates new file. If files is already present, error code will be returned.
    • FA_CREATE_ALWAYS - Creates new file. If files is already present then overwrites it.

Functions

  • DSTATUS disk_initialize (BYTE drv)

Initializes drive. Parameters:

  • drv - Drive number. In most cases 0.
  • Returns DSTATUS code.
  • DSTATUS disk_status (BYTE drv)

Displays drive status. Parameters:

  • drv - Drive number. In most cases 0.
  • Returns DSTATUS code.
  • FRESULT f_mount (BYTE Drive, FATFS* FileSystemObject)

Initializes file system. Parameters:

  • Drive - Drive number. In most cases 0.
  • FileSystemObject - File system object pointer.
  • Returns FRESULT code.
  • FRESULT f_open (FIL* FileObject, const TCHAR* FileName, BYTE ModeFlags)

Opens or creates file. Parameters:

  • FileObject - File system object pointer.
  • FileName - File name.
  • ModeFlags - Open mode flag.
  • Returns FRESULT code.
  • FRESULT f_close (FIL* FileObject)

Closes file. Parameters:

  • FileObject - File system object pointer.
  • Returns FRESULT code.
  • FRESULT f_read (FIL* FileObject, void* Buffer, UINT ByteToRead, UINT* ByteRead)

Reads required amount of bytes from file. Parameters:

  • FileObject - File object pointer.
  • Buffer - Buffer pointer where to store data.
  • ByteToRead - Number of files to be read.
  • ByteRead - Variable pointer where read bytes are returned.
  • Returns FRESULT code.
  • FRESULT f_write (FIL* FileObject, const void* Buffer, UINT ByteToWrite, UINT* ByteWritten)

Writes required amount of bytes to file. Parameters:

  • FileObject - Point to file object.
  • Buffer - Point to data being written into file.
  • ByteToWrite - Number of bytes to be written.
  • ByteWritten - Point to variable where written bytes are returned.
  • Returns FRESULT code.
  • FRESULT f_sync (FIL* FileObject)

Writes data from buffers to a file to save them from power loss. Used in applications where a file is open for a long time. Parameters:

  • FileObject - Point to file object.
  • Returns FRESULT code.
  • FRESULT f_mkdir (const TCHAR* DirName)

Creates folder. Parameters:

  • DirName - Folder name.
  • Returns FRESULT code.
  • FRESULT f_unlink (const TCHAR* FileName)

Deletes file or folder. Parameters:

  • FileName - Object name.
  • Returns FRESULT code.
  • FRESULT f_rename (const TCHAR* OldName, const TCHAR* NewName)

Rename file or folder. Parameters:

  • OldName - Object old name.
  • NewName - Object new name.
  • Returns FRESULT code.
  • TCHAR* f_gets (TCHAR* Str, int Size, FIL* FileObject)

Reads string with given length from file. Parameters:

  • Str - Buffer where to save read data.
  • Size - Length of string.
  • FileObject - Point to file object.
  • Returns Str buffer if successful.
  • int f_putc (TCHAR Chr, FIL* FileObject)

Adds a char to file. Parameters:

  • Chr - Char to be added into file.
  • FileObject - File object pointer .
  • Returns 1 if successful.
  • int f_printf (FIL* FileObject, const TCHAR* Foramt, …)

Adds a formated string to file. Parameters:

  • FileObject - File object pointer.
  • Foramt - String format.
  • Returns the number of written chars if successful.
  • DWORD f_tell (FIL* FileObject)

Cursor position in file. Parameters:

  • FileObject - File object pointer.
  • Returns read/write cursor position in file as a pointer.
  • FRESULT f_lseek (FIL* FileObject,DWORD Offset)

Move cursor to desired position in file. Parameters:

  • FileObject - File object pointer.
  • Offset - Desired position in bytes from the beginning of the file.
  • Returns FRESULT code.

 

Example

#include #include #include

int main (void) {

  static FATFS FATFS_Obj;
  FIL fil_obj;
// SD card initialization. 
disk_initialize(0);
// File system initialization. 
f_mount(0, &FATFS_Obj);
// Create text file "file.txt".
f_open(&fil_obj, "/file.txt", FA_CREATE_NEW);
// File to be open for writing.
f_open(&fil_obj, "/file.txt", FA_WRITE);
// Writing into file.
f_printf(&fil_obj, "SD Card test");

Close file. f_close(&fil_obj); } /home/www/roboticlab/homelab_data/pages/en/files|Download software.txt— MISSING PAGE — ====== Practical Examples ====== Practical examples are built up in uniform style and as concrete as possible. Each example begins with a short introduction of the theory and gives necessary knowledges for completing the following practical part. Practical part contains commented example of the source code of the software. Generally the library of the HomeLab is used in the example of the code, but in some cases the registers are also configured. The first chapter is a little bit different with a bit different goal. It describes installation and set-up of necessary software. The examples are about Windows and Linux operation systems. Chapters and practical examples after the first chapter are suitable for both OS and development software.

 
Buildup There is a list of necessary knowledges to complete the example at each chapter of practical examples. In this list are references to other chapters of the book, which are marked with icons as follows: * [HW] Physical module used in th example. * [LIB] Part of the software library used in the example. * [ELC] Reference to the chapter Basics of electronics. * [AVR] Reference to the chapter AVR microcontroller's module. * [PRT] Reference to other exercises. Basic software of the examples As mentioned before, practical code samples are composed on the basis of the library of the HomeLab. There are most used specific AVR operations and procedures connected with the HomeLab’s modules written in the library. The usage of the library means that in order to start the modules the user does not have to write a hardware-like, program code which uses registers, although this opportunity always exists. Separating the software which communicates with hardware from the examples and exercises, allows the user to focus on creating his/hers own algorithm instead of peculiarities not connected to the hardware. Code style of the examples The example programs are written in one style, to achieve more synoptic program code. Uniform style makes the program more readable and prevents making simple syntax mistakes. It is advised to follow a certain style when making exercises. The main characteristics of the style: * Program, all its functions and variables are in English and in small letters, the words are separated with an under-strike. * Functions are in following form: object_action_subject. * more important places in the program are commented. * Every block in C-language (marked with { and } )starts and begins in separate row. * Blocks are tabulated with tabulator keys. Tabulator is not used inside rows. ===== Setup ===== An environment for writing the code, a compiler for the corresponding language and software for uploading written programs to the controller are needed in order to program the AVR controller. The most comfortable method would be by using special integrated developing environment (IDE). The AVR microcontroller can be programmed in many different programming languages: assembler, C, C+, Pascal, Basic, etc. This instructions focus on using the C-language when programming the microcontroller. There is free software for programming AVR microcontroller for the Windows OS, the Linux OS and the Mac OS. There exists Atmel's AVR Studio proprietary software and free open-source software like Eclipse and Code::Blocks for AVR microcontroller C-language programming. For installation, the Robotic HomeLab development software must be downloaded for your operating system. The needed software is IDE, AVR compiler, Robotic HomeLab library, programmer driver, programming utilities and examples. Well known Eclipse and Code::Blocks IDE development environment are supported for Robotic HomeLab kit. Special package is bundled for Windows and Linux operating systems containing IDE, library, AVR plugin, programmer drivers, project templates and examples. However alternatively one can use well known AVR Studio for Windows. All software packages can be downloaded from Robotic HomeLab webpage or from original software developer webpage.
 
==== IDE CodeBlocks ==== The following guide describes the use of the CodeBlocks environment for programming HomeLab Controller Module. This is based on CodeBlocks enviroment, specially adapted for Homelab with a set of packaged software and accessories. Modified CodeBlocks enviroment are downloadable website: http://home.roboticlab.eu/et/files === Creating a new project === To create the new project, select in menu
File→New→Project. There should be selected a project template according to HomeLab generation and configure it as desired. When HomeLab project template is used, then the values are already filled, and there is no need to change anything around. The following example dialog boxes are based on the Robotics HomeLab III. After choosing a right version of HomeLab generation then enter the project name and set the location to save the file (it is preferable to avoid the use of umlauts). Then you can set the project compiling folder and in the next window, enter microcontroller parameters.
 
=== Using CodeBlocks === Once the project is created, then the new project appears in the left tree with the
main.c file, which includes existing simple example code. To compile press the gear icon in the toolbar or by pressing F7. If the compilation succeeds then in the bottom Build Log window the user program memory count are displayed or if not, then error messages in the event of failure. When loading the program into the microcontroller, in case HomeLab III, first should be entered into the bootloader by holding down the button S0 on the Controller module and at the same time pressing the reset button to restart. When the blue LED lights up, then the Controller is ready for downloading a new program. In previous HomeLabs a bootloader mode is not available. Compiled program can be downloaded to the controller from the Tools menu by choosing the right HomeLab programmer. In the case of HomeLab III choose HomeLab III or CTRL+F7. ==== IDE CodeBlocks manual setup ==== The following guide describes the AVR development environment setup, if not used HomeLab precompiled installing package. === Installing software === It is necessary to install the following software bundle: 1. CodeBlocks CodeBlocks IDE (Integrated Development Environment), for software writing and its loading into the microcontroller. 2. ATMEL AVR Toolchain AVR Toolchain is GNU-GCC compiler for AVR microcontrollers. This is a freeware which can be found on Atmel's website. 3. HomeLab library HomeLab library contains a various functsions to make AVR and HomeLab kit programming simpler. The last versions for this library can be found on HomeLab website. 4. DFU-Programmer DFU-Programmer is for programming HomeLab III series controller and using its bootloader —- = CodeBlocks installation = Following guide describes HomeLab III (Controller v1 - ATxmega128A1U) development enviroment setup and use in Windows operating system. First install CodeBlocks software. No need to install CodeBlocks plugis. Next choose correct location for CodeBlocks. All examples are in default location C:\HomelabCB Then CodeBlocks software install on the computers. = Adding Homelabs extras = When CodeBlocks are installed, then add: AVR Toolchain, HomeLab library, DFU-Programmer First of all, you should choose the folder where you installed the CodeBlocks, because of all the extras installed in the same folder. === CodeBlocks setup === The first launch prompted compiler location. May be select *No Compiler*, because the choice of the compiler is set manually at a later, and it is dependent to the project template. Then, the compiler should be set. Enter the menu Settings → Compiler…. In the opened window should be set to the following lines: Observe that would be selected GNU GCC Compiler for AVR and show where to install the software. If the installed sowtware location is not C:\HomelabCB then should be made corresponding changes themselves. Then configure the programmer to be able to download the code directly from CodeBlocks environment. In order to find the menu Tools → Configure tools… and choose Add. In the opened windows write the following rows dependent HomeLabs generation: HomeLab III * Homelab III * C:\HomelabCB\Programmer\Program.bat * „C:\HomelabCB\Programmer“ „${TARGET_OUTPUT_BASENAME}.hex“ * ${TARGET_OUTPUT_DIR} HomeLab II (Atmega2561) * Homelab 2561 * C:\HomelabCB\Programmer\HL Flash\hlflash.exe * ${TARGET_OUTPUT_BASENAME}.hex * ${TARGET_OUTPUT_DIR} === Linux/Ubuntu setup=== Install Codeblocks extras: sudo apt-get install codeblocks-contrib To run dfu-programmer with a normal user privileges, create under /etc/udev/ folder a ruled.d file with following content: SUBSYSTEM==„usb“,ACTION==„add“,ATTRS{idVendor}==„03eb“,ATTRS{idProduct}==„*“,GROUP=„plugdev“ It is also necessary to install the library. Typically AVR libraries are located in the folder /usr/lib/avr It is necessary to own administrator rights to add a folder for the new library. If the AVR Toolchain repositorys not yet been updated, you may receive an error message for ADC function. To correct this replace manually in the avr folder iox128a1u.h file (included in the library). To make programming simpler create a following batch file: sudo nano /usr/bin/homelab-programmer copy the content of the file: #!/bin/bash dfu-programmer atxmega128a1u erase dfu-programmer atxmega128a1u flash $1 dfu-programmer atxmega128a1u start crant execution permission: sudo chmod 775 /usr/bin/homelab-programmer Codeblocks Tools→Configure tools … Set the programmer is as follows. Add library support Settings → Compiler … === CodeBlocks creating a project === Go to menu File→New→Project. There should be selected a project according to HomeLab version and configure it as desired. First, choose the name and location of the project. Avoid the use of umlauts. Then select the project compiling folder. It is recommended to not change it. Then choose a microcontroller and used frequency. Lastly, AVR Toolchain installation folder should be set. === Using the CodeBlocks === Once the project is created, then the new project appears in the left tree with example code. To compile press the gear icon in the toolbar. If the compilation succeeds then in the bottom Build Log window the user program memory count are displayed or if not, then error messages in the event of failure. When loading the program into the microcontroller, in case HomeLab III, first should be entered into the bootloader by holding down the button S0 on the Controller module and at the same time, press the reset button to restart. In previous HomeLabs a bootloader mode is not available. If all the necessary drivers are installed (drivers are in CodeBlocks / Programmer folder), then can be download compiled hex file. To start programmer, go to Tools menu. ==== Code::Blocks installation MS Windows ==== The following guide will help to install Code::Blocks HomeLab package in MS Windows enviroment. This example is based on Windows 7, but is usable with Windows XP and Windows 8 with a small differences. Code::Blocks HomeLab package can be downloaded from the HomeLab website. === Software installation === 1. Download the latest Code::Blocks HomeLab pack Robotic HomeLab website (home.roboticlab.eu): http://home.roboticlab.eu/et/files 2. Run the downloaded file HomeBlocks installation window opens. It is recommended to install the software package in the default folder (usually C:\Homeblocks). The next step will be to change the Start menu shortcut name and location. The shortcut on the desktop is recommended, but it is always possible to open the program from the Start menu. Next, the summary window will appear stating the selected installation settings. Clicking the Install button will start the installation. When the installation has been finished, press the Finish button. Use desktop shortcut to open a work enviroment or go to Start menu → Windows 7 All Programs Windows XP ProgramsHomelab CodeBlocks. 3. Connect HomeLab Controller and wait for Windows when it is finished installig the appropriate drivers. In many cases, the drivers will install automatically and requires no user intervention. If you press the bottom right corner of this message, the installation windows of the driver will open (in Windows 7). Before continuing, we should wait until the end of the installation of drivers. In some cases, Windows will not be able to automatically find the drivers needed. In this case, it must be installed manually and it is located in the drivers folder nt C:\HomeBlocks\Programmer. Driver installation results is possible to verify the Device Manager.
 
==== Installing Eclipse for Windows ==== This section describes how to install Robotic HomeLab development environment in MS Windows operation systems. Bundled software package can be downloaded only from Robotic HomeLab webpage. === Software installation === 1. Download latest „Eclipse HomeLab bundle“ from http://home.roboticlab.eu/en/files 2. Run the installation file Installation window will popup. It is recommended to install software to default folder: C:\Eclipse Next window defines Start Menu group Desktop icon can be selected, if an icon on the Windows desktop is required Next window is summarizing the install configuration and pressing
Install installation process will begin. If setup is completed press Finish. To start IDE find it from Start menu Robotic HomeLab IDE group → Robotic HomeLab IDE. 3. Connect Robotic HomeLab Controller module and wait until Windows initializes necessary drivers. In most cases driver installation works without the need of special driver installation file and Windows finds correct drivers automatically. If you click on the installation process message on the right down corner (Windows 7) similar window should be seen. Before going further please wait until this process is successfully finished. In case Windows cannot find driver automatically you can find them from Robotic HomeLab IDE folder which is by default C:\Eclipse\ftdi-drivers\ In case of doubt of successful install of drivers you can open Device Manager and confirm that no problematic driver is pointed out. ==== Installing Eclipse for Linux ==== This section describes how to install and use AVR development environment in Linux Ubuntu operation systems. For installation software repository of Robotic HomeLab is used. === Software automatic installation === 1. Software source setup For source setup HomeLab-keyring software package must be downloaded and installed. Download it from webpage: homelab-keyring. Next, Internet browser will open a window where opening package installation with automatic installation manager can be selected. If you select the correct option the manager will open (Ubuntu 10.04 example). Ubuntu 10.10 and newer „Ubuntu Software Center“ will popup. Press „Install package“ for installation and enter root password. If the installation has finished close the manager. As a conclusion you have successfully installed Robotic Homelab software source. 2. Robotic HomeLab software installation To install Robotic HomeLab software in Gnome choose from menu: Applications → Programming → Install Homelab In case of Unity start typing: homelab in Dash Enter root password when asked. If the password is correct terminal window will open and software installation will begin. If not installation will not start. Setup can be started later again if first attempt was unsuccessful. Software installation might take some time from few minutes to a quarter of hour depending on your Internet connection and computer speed. As a result the following software packages will be installed: * HomelabSetup - HomeLab configuration program * Eclipse-CDT - development environment * gcc-avr – GNU C-language compiler for AVR platform * avrdude – program for loading HEX to microcontroller * avr-libc – C-language libraries for code writing into AVR platform * libhomelab - HomeLab library * hlflash - HomeLab flashing program * hlflash-gui - HomeLab flashing GUI * hlinit - HomeLab initialization program Terminal will close after installation of these software packages. Robotic HomeLab software is now successfully installed! === Software manual installation === In case automatic installation fails at some reasons required software packages can be also installed manually. 1. At first add Robotic HomeLab repository through terminal into Ubuntu package manager. The following line can be copied into terminal to do this: sudo add-apt-repository http://roboticlab.eu/repo/ubuntu/ 2. GnuPGP key installation Because of all Robotic HomeLab software packages contain GnuPGP key for validation you also need to install corresponding public key into your computer. Download key from webpage: homelab-keyring.gpg.zip Extract archive using user interface or terminal. Corresponding command in terminal: unzip homelab-keyring.gpg.zip Then add this key into Ubuntu package manager. When in folder that contains homelab-keyring.gpg type: sudo apt-key add homelab-keyring.gpg 3. Download all software updates. Use the following line for update : sudo apt-get update After downloading updates the following software packages are required to be installed: * eclipse * eclipse-cdt * urjtag-homelab * hlflash * hlinit * hlflash-gui * libhomelab * avrdude-homelab * eclipse-avr Copy this line into terminal for installation: sudo apt-get install eclipse eclipse-cdt urjtag-homelab hlflash hlinit hlflash-gui libhomelab avrdude-homelab eclipse-avr After completing installation of those software packages Robotic HomeLab is successfully installed! To create new project and configure floating-point variables look at the instructions for Eclipse setup. /home/www/roboticlab/homelab_data/pages/en/examples/setup/eclipse/install/mac.txt— MISSING PAGE — ==== IDE Eclipse ==== === Creating new project === In order to write a program for the controller you need to create the new project. The project includes typically different files like source codes, header files, compiled program files, etc. It is strongly advised to create new folder for every project (which is offered also by the New Project Wizard. The following steps have to be completed when creating new project with the help of wizard: 1. Start Eclipse (Robotic HomeLab IDE) and ja setup new project. If the software is newly installed, project repository Workspace must be created. To do this, select the Workspace folder location in main window where the repository will be created. To create the new project, select in menu File - New - C project. Add project name and click Next. 2. Project configuration in the next dialog box should be selected as only Release. 3. In the next window, microcontroller type and working frequency must be selected. Robotic HomeLab (v5) microcontroller is ATmega2561 working frequency 14745600 Hz. To finish project setup click Finish. 4. After this the user interface for program development will open. Before you can start writing code, new file for source code is needed to create. To do this, click mouse right button on your fresh project, select New - Source File and input a name to it, which must be ended with “.c„. It is recommended to name the main file as „main.c“. After pressing Finish button, a new file is created and opened in development environment. 5. Before you start writing the source code, it is advisable to make some changes in preferences for easier use of development environment. Choose from menu Window - Preferences and navigate from leftside tree to General - Workspace and select option Save automatically before build 6. For testing the correct operation of Eclipse, the following source code can copied to environment and compiled. For compilation the keyboard combination of CTRL + B can be used. A simple test code which is not using HomeLab library #include

int main(void) {

unsigned int x,y;
// Set pin PB7 as output
DDRB = 0x80;

Infinite loop while (1) { Invert pin PB7

	PORTB ^= 0x80;
	y=3200;
	while(y--){ 
  			x=260;
  			while(x--){
  				asm volatile ("nop");
  			}
		} 
}

}

For successful compilation, the code is needed to be error free and the compilator must be able to find all necessary header files. A successful compilation is indicated in Problem window as emptiness (or at outermost cases some warnings Warning) and in Console window as the output of compilator which will for example be in this case:

AVR Memory Usage
----------------
Device: atmega2561
Program:     308 bytes (0.1% Full)
(.text + .data + .bootloader)
Data:          0 bytes (0.0% Full)
(.data + .bss + .noinit)
Finished building: sizedummy

If the code has errors or header files are not found, then the Console window displays the number of errors on end line and describes possible faults above it.

../main.c: In function 'main':
../main.c:23: error: expected ';' before 'while'
../main.c:13: warning: unused variable 'x'
make: *** [main.o] Error 1

Alsothe Problems window displays several error messages and corresponding location in code is marked with error icon.

7. For using HomeLab library, it is assumed to be correctly installed into operation system with the help of instruction. For every project the library must be included into list of linkable objects in project options. To do this, open at first: Project → Properties and then from leftside tree C/C++ Build → Settings, further Tool Settings → AVR C linker → Libraries. Choose in window that opened in the right under Libraries (-l) icon Add… and input to the dialog box „homelab2561“. Then OK and one more OK.

8. For testing HomeLab library the following source code can be used when copied besids the previous code and compiled. You can again use CTRL + B combination on keyboard.

A simple test code which uses HomeLab library #include #include int main(void) { Set pin PB7 as output

DDRB = 0x80;
// Infinite loop
while (true)
{
	// Invert pin PB7
	PORTB ^= 0x80;
	hw_delay_ms(500);
}

}

If compilation of this code is also successful, the development environment was set up correctly.

 

Loading the code into microcontroller

1. Connect the microcontroller board to PC using USB cable. After successful connection a small green LED labeled as PWR will light up (after some time on first connection).

2. Set options for program loader (AVRDude). For this again open project properties Project → Properties and from leftside tree AVR → AVRDude, further Programmer configuration → New. The dialog box that now opens needs no changes and you can press OK button. If it is selected press Apply and then OK.

It is important to check that in list Programmer configuration something can be choosed and by default this will be: New Configuration.

3. If HomeLab microcontroller module is connected with PC, you can now try to load the compiled program into microcontroller. For this simply press AVR icon or use CTRL + ALT + U in keyboard.

As an effect of this program, the on-board LED (PB7) should start flashing. If the program works, you have successfully set up your programming environment and completed your first program. Congratulations!

Using floating-point variables

It is sometimes necessary in AVR programs to use floating-point variables. For calculating with them and presenting with printf-type functions, the following changes are necessary in the configuration of the project:

1. Open the configuration of the project from the menu File → Properties. On the leftside panel open AVR C Linker → Libraries, where in addition to HomeLab library other library objects must be included printf_flt and m (libprintf_flt.a ja libm.a).

2. Then open AVR C Linker → General and into box of Other Arguments add line -uvfprintf.

3. Press OK and close configuration window. /home/www/roboticlab/homelab_data/pages/en/examples/setup/eclipse/atmega128.txt— MISSING PAGE —

AVR Studio 4

This section contains the information necessary to install AVR development software on Windows operating system.

Installation

You need the following software which can be downloaded from manufacturers homepage or acquired from the CD supplied with the Robotic HomeLab kit.

1. AVR Studio

AVR Studio 4 IDE (Integrated Development Environment) is a base software for writing the source code, compiling it and uploading the program to the controller. AVR Studio can be downloaded from Atmel homepage.

2. WinAVR

WinAVR is a GNU-GCC compiler for AVR microcontrollers. This is a freeware which can be downloaded from Sourceforge webpage. During the installation process WinAVR offers a folder name containing long version number. We suggest to cut the version number from folder name and install it just like shown below:

C:\WinAVR

3. Robotic HomeLab library

Robotic HomeLab library is a set of functions designed for Robotic HomeLab kit and AVR controllers. By using the library the programming is much easier and effective. Latest version of the library can be downloaded from the Robotic HomeLab webpage. This library should be installed in the same folder where WinAVR was installed.

For ATmega2561 based Robotic HomeLab

4a. JTAG liides

JTAG liides - HappyJTAG2 on liides programmaatori ja AVR Studio vahele. Tarkvara on pakitud zip failiks ja piisab selle lahtipakkimisest soovitud kataloogi näiteks C:\WinAVR (tarkvara eraldi paigaldada ei ole vaja) HappyJTAG2 for HomeLab

5a. Programmaatori ajur

Ajur võimaldab arvutiga ühendada programmaatori, mis asub kontrolleri plaadil. Kui ühendada kontrollerplaat arvutiga USB liidese kaudu peaks Windows teostama automaatse paigalduse (Windows 7). Kui avada paigalduse protsessi aken peaks nägema umbes järgmisi teateid:

Enne järgmist sammu tuleks oodata, kuni paigaldamine on täielikult valmis.

For ATmega128 based Robotic HomeLab

4b. Virtual COM port driver

Driver enables to connect USB JTAG-ICE programmer with your PC. Driver have to be installed before connecting the programmer. Driver file name is „CDM x.xx.xx.exe“, where „x“ denotes the version number. After installing the driver you can connect the JTAG-ICE programmer through the USB port and let Windows to detect the device automatically. You should see the notice on the windows task bar.

Notice of finding the new device

According to number of virtual ports previously defined on the particular computer the windows assigns next port number for the new device. New COM port name (range number) is generated if the device is plugged in to the same computer using another USB port. Some AVR Studio versions can not use the programmer if the COM port number exceeds number 10 and number 4 in case of using it as debugger. To prevent this situation you can modify the assigned port number in Device manager and assign it to the range COM0…COM4. See the complete procedure here .

AVR Studio for ATMega128

Creating new project

In order to write a program for the controller you need to create the project space. The project includes typically different files like source codes, header files, compiled program files, etc. It is strongly advised to create new folder for every project (which is offered also by the New Project Wizard).

Following steps have to be completed when creating new project with the help of wizard.

1. Open AVR Studio and press New Project. If the dialog box is not opened automatically select Project - New project from the menu bar. Press Next.

2. Next dialog box is about compiler and initial settings. Select AVR GCC compiler. On the left, insert the name of the project and main source file name. The source file name should have extension “.c„. Two check boxes should be also checked, which will create the new folder and initial file. You should also show the folder where project files will be created. After proper selections press Next.

NB! If AVR GCC is missing on the compiler list, it is not properly installed. In that case the WinAVR software have to be installed before starting to write C source code.

3. On the next dialog box you have to select the debugger platform and microcontroller. HomeLab kit is using JTAG ICE as debugger platform and ATmega128 as microcontroller. After selections press Finish.

4. Now the project space is created and new window will open where you can start to write the program source code.

5. You need to set some project parameters before the first compilation. The important parameters are controller frequency and optimization method. HomeLab controller has frequency 14,7456 MHz (14745600 Hz). The frequency can be set in the project properties with Hz (not MHz): Project → Configuration Options → General. Optimization method should left -Os, if there is no need for other methods.

6. For using HomeLab library functions the software have to be properly installed. Every new project requires adding library to list of linked objects. To do that go to Project → Configuration Options → Libraries and add object „libhomelab.a“.

If object libhomelab.a is missing from the left list the library is not properly installed to the system and it should be reinstalled.

Setting's test

After set up of the development environment it is wise to test it, for ensuring its correctness. Simplest way is to write a short program, compile it and upload to controller.

1. Connect the programmer with ATmega128 board. Be sure that the programmer is correctly connected to JTAG connector (cable is directed away from controller board- see next picture). Connect the controller board supply (small green LED should light up if correct power supply is connected).

Insert simple C source code:

#include #include

int main(void) {

// Pin PB7 to output
DDRB = 0x80;
// Endless cycle
while (true)
{
	// Pin PB7 invertion
	PORTB ^= 0x80;
	hw_delay_ms(500);
}

}

Compilation and programmer buttons

Compile the project with Build command (keyboard F7). Make sure that the compilation succeeded. For this you should see the following message on the message window.

Build succeeded with 0 Warnings...

2. Open the controller window Tools → Program AVR → Auto Connect. Be sure that the tab Program is open.

If the described window does not open and Connection Failed window is opened instead you do not have proper connection with the board or programmer. First check that micrcontroller is correctly powered (green LED is on) and the programmer is properly connected to JTAG connector. If this is OK check the COM port number which is assigned by the Windows. If this is greater than 9, the AVR Studio can not recognize the programmer. Follow the instructions given in the beginning of the chapter and assign the port number between 0 and 4.

3. On the programmer window insert into Flash-section textbox Input HEX File the location of the compiled program by pressing the “…„ button. Compiled program is usually located in the project folders sub folder default and has same name as the project but with the extension “.hex„, for example „labor1.hex“. After selecting correct file press button Program which uploads the program to the controller. If all went well you should see the following message on the end of the window:

OK
Reading FLASH input file.. OK
Setting device parameters for jtag programming ..OK
Entering programming mode.. OK
Erasing device.. OK
Programming FLASH ..       OK
Reading FLASH ..       OK
FLASH contents is equal to file.. OK
Leaving programming mode.. OK

According to the program the on-board LED (PB7) should start flashing. If the program works you have successfully set up your programming environment and completed your first program. Congratulations!

Debugger
The list of registers in the debugger of the ATmega128.

Debugging a program means searching errors from the program. For that programs called debuggers are created, they allow to execute the program step by step and stopping it where it is needed. Such implementation of the program allows checking the values of the variables at any phase of the program, contents of the registers and the sequence of executing the program. Debugging is especially important while dealing with more complex programs where it is often difficult to find errors. With microcontrollers, it is important that step-by-step implementation of program is done in the controller, which allows seeing change of real outputs in addition to the values of the registers. Two conditions must be met for using a debugger: microcontroller must support debugging and you must have necessary hardware – JTAG programmer which allows debugging. Cheaper programmers using ISP programming interface may upload compiled program into the controller but not necessarily allow debugging.

To start the program in debugging mode with the AVR Studio, firstly it should be compiled by pressing button build (F7) and the compiled program started with the command Run (F5). Before that break points (F9) can be added to selected palces in the source code. When implementation of the program reaches the break point, the program is stopped for determining the state of the microcontroller in that point. Implementation of the program may be continued with command Run again or use Step Into (F11) for implementing the program one command at the time.

The usage of floating-point variables

Some times in AVR program it is necessary to use floating-point variables. For calculating with them and presenting with printf-type functions, the following set-up changes must be done to the configuration of the project:

1. Open the set-up of the project from the menu Project → Configuration Options. Add libprintf_flt.a and libm.a after libhomelab.a of the library of HomeLab in the configuration tab Libraries.

2. Next, open tab Custom Options and chose [All files]. Next add lines with “-lprintf_flt„ ja “-lm„ to the box on the right and line with “-uvfprintf„ to the [Linker Options] section.

3. Press OK and close configuration window.

AVR Studio for Windows ATmega2561

Projekti loomine

Kui arendustarkvara on paigaldatud saab alustada programmi kirjutamist. AVR kontrolleri programmi kirjutamiseks tuleb luua uus projekt, mis tüüpiliselt sisaldab endas palju erinevaid faile: programmikoodi(e), päisfaile, kompileeritud programmi jne. Selleks et projektid oleks korrektselt eristatavad, tuleks iga projekti jaoks luua uus kataloog (seda võimalust pakub uue projekti loomise abimees).

Uue projekti loomiseks tuleb läbida järgmised sammud:

1. Avada AVR Studio ja vajutada nupule uus projekt (New Project). Juhul kui vastav aken automaatselt ei avane, valida menüüst Project - New project. Pärast sobivat sisestust vajutada nupule Next.

2. Avaneb aken, kus tuleb märkida kompilaatori ja failide algseaded. Kompilaatoriks valida AVR GCC ja paremas akna osas sisestada projekti nimi ning algkoodi faili nimi. Algkoodi faili nimi peaks kindlasti lõppema laiendiga “.c„. Aknas on võimalik veel märkida valikud automaatseks projekti nimega kataloogi ja algkoodi faili tekitamiseks. Mõlemad valikud on mõistlik ära märkida. Samuti tuleks näidata kataloog, kuhu vastav projektikataloog tekitatakse. Pärast valikute tegemist vajutada nupule Next.

NB! Kui kompilaatori valikus puudub AVR GCC, siis ei ole WinAVR korrektselt paigaldatud ja seda tuleks enne C-keele programmi kirjutamist kindlasti teha.

3. Järgnevalt avaneb aken, kus tuleb märkida kasutatav silumise platvorm ja mikrokontrolleri tüüp. Kodulaboris (v5) on silumise platvormina kasutusel JTAGICE mkII programmaator ja mikrokontrolleriks on ATmega2561. Projekti lõplikuks loomiseks vajutada nupule Finish.

4. Nüüd avaneb juba programmeerimise kasutajaliides, kuhu saab hakata kirjutama programmi lähtekoodi.

 

5. Enne koodi kompileerimist tuleb määrata projekti seaded. Olulisemad seaded on kontrolleri taktsagedus ja kompilaatori optimeerimismeetod. Kodulabori kontrolleri taktsagedus on 14,7456 MHz ehk 14745600 Hz. See sagedus tuleb hertsides määrata Project → Configuration Options → General aknas. Optimeerimise meetodiks jätta -Os, kui ei ole konkreetset vajadust teiste meetodite järgi.

6. Kodulabori teegi kasutamine AVR Studio-ga eeldab, et see on tarkvara paigaldamise juhendi kohaselt süsteemi paigaldatud. Iga projekti korral tuleb teek projekti seadetest Project → Configuration Options → Libraries lisada lingitavate objektide nimekirja.

Kui objekt libhomelab2561.a nimekirjast puudub, siis ei ole Kodulabori teek korrektselt süsteemi paigaldatud.

 

Seadistuste testimine

Kui arenduskeskkond on esimest korda paigaldatud ja seadistatud, on mõistlik testida, kas kõik sai tehtud õigesti. Selleks on lihtsaim viis teha üks väike programm, see ära kompileerida ja laadida kontrollerisse.

1. Ühendada kontrollerplaat USB kaabliga arvutiga. Peale kontrollerplaadi ühendamist peaks süttima väike roheline toite LED - PWR.

2. Käivita liidesprogramm HappyJTAG2 ja seejärel AVR Studio. Oluline on sammude järjekord. Esmalt tuleb ühendada kontroller arvutiga ja veenduda, et kontroller lülitub sisse. Seejärel käivitada programm HappyJTAG2 ja AVR Studio.

3. AVR Studios luua vajadusel projekt ja sisestada lihtne C-kood:

Testida võib kahte erinevat koodi. Esimene neist kasutab Kodulabori teeki, teine teeb sama asja ilma teegita.

Lihtne testprogramm, mis kasutab Kodulabori teeki. #include #include int main(void) { Viigu PB7 seadmine väljundiks

DDRB = 0x80;
// Lõputu tsükkel
while (true)
{
	// Viigu PB7 inverteerimine
	PORTB ^= 0x80;
	hw_delay_ms(500);
}

}

Lihtne testprogramm, mis ei kasuta Kodulabori teeki. #include int main(void) { unsigned int x,y; Viigu PB7 seadmine väljundiks

DDRB = 0x80;

Lõputu tsükkel while (1) { Viigu PB7 inverteerimine

	PORTB ^= 0x80;
	y=3200;
	while(y--){ 
  			x=260;
  			while(x--){
  				asm volatile ("nop");
  			}
		} 
}

}

Kompileerimise ja programmaatori nupud

Kompileerida programm käsuga Build (kiirklahv F7) ja kontrollida, et kompileerimine õnnestus. Selleks peab teadete aknasse tekkinud kompilaatori väljundi lõpp olema järgmine:

Build succeeded with 0 Warnings...

 

4. Avada koodi laadimise aken nupust Tools → Program AVR → Auto Connect. Tulemuseks peaks avanema kompileeritud faili mikrokontrollerisse laadimise aken. Kontrollige, et avatud oleks kaart Program.

Kui eespool toodud aken ei avane ja avaneb aken Connection Failed, siis puudub ühendus programmaatoriga. Esmalt tuleks kontrollida, kas mikrokontrolleril on järel toide. Kui see on korras, siis tuleks kontrollida HappyJTAG2 programmi oleku indikaatoreid. FT2232 ja AVRStudio peaks olema rohelised.

5. Programmaatori aknas sisestada Flash-sektsioonis tekstikasti Input HEX File kompileeritud fail. Seda saab teha “…„ nuppu vajutades. Kompileeritud fail asub tavaliselt projekti alamkataloogis default ja see on sama nimega, mis projekt, kuid laiendiga “.hex„, näiteks „labor1.hex“. Pärast õige faili valimist vajutada nupule Program, mis laeb valitud programmi kontrollerisse. Kui kõik õnnestus, tekib programeerimiskeskkonna allosasse teade:

OK
Reading FLASH input file.. OK
Setting device parameters for jtag programming ..OK
Entering programming mode.. OK
Erasing device.. OK
Programming FLASH ..       OK
Reading FLASH ..       OK
FLASH contents is equal to file.. OK
Leaving programming mode.. OK

Programmi mõjul peaks kontrolleri plaadil olev oleku-LED PB7 perioodiliselt süttima ja kustuma. Kui programm töötab, on tarkvara paigaldatud edukalt ja esimene projekt tehtud. Palju õnne!

Siluri kasutamine
ATmega registrite loetelu siluris

Programmi silumiseks (inglise keeles debugging) nimetatakse vigade otsimist programmist. Selleks on loodud eraldi vahendid - silurid (inglise keeles debugger), mis võimaldavad programmi täita samm-sammult, peatades seda soovitud kohtades. Selline programmi täitmine võimaldab igas programmi faasis kontrollida muutujate väärtusi, registrite sisusid ja programmi täitmise järjekorda. Eriti oluline on silumise võimaluse kasutamine keerukamate programmide juures, kus vea põhjust on tihti keeruline otsida. Mikrokontrollerite puhul on veel oluline, et tarkvara samm-sammult täitmine toimub reaalselt kontrolleris ja võimaldab nii lisaks registrite väärtuste vaatamisele näha ka reaalsete väljundite muutumist. Siluri kasutamiseks on eelkõige vaja kahte tingimust: kasutatav mikrokontroller peab silumist toetama ja peab olema silumist toetav riistvara - JTAG programmaator. Odavamad programmaatorid, mis kasutavad ISP programmeerimise liidest, võimaldavad laadida kontrollerisse kompileeritud programmi, kuid ei võimalda silumist.

Programmi käivitamiseks siluri režiimis AVR Studio-ga tuleks see esmalt kompileerida nupuga Build (kiirklahv F7) ja käivitada kompileeritud programm käsuga Run (kiirklahv F5). Programmi lähtekoodi võib enne seda soovitud kohtadele lisada katkestuspunkte (inglise keeles break point) (kiirklahv F9). Kui programmi täitmine jõuab katkestuspunktini, peatatakse programmi töö, võimaldades nii uurida mikrokontrolleri olekut sellesse punkti jõudmisel. Programmi täitmist võib jätkata jällegi käsuga Run või siis kasutada käskhaaval täitmist käsuga Step Into (kiirklahv F11).

Ujukoma-arvude kasutamine

Mõnikord tekib vajadus AVR programmis kasutada ujukoma-arve. Nendega arvutamiseks ja nende esitamiseks printf-tüüpi funktsioonidega tuleb projekti seadistustes teha järgmised muudatused:

1. Avada projekti seaded menüüst Project → Configuration Options. Seadete kaardil Libraries tuleb sinna, kuhu on lisatud Kodulabori teegi objekt libhomelab.a, järgi lisada ka libprintf_flt.a ja libm.a.

2. Seejärel tuleb avada Custom Options kaart ja valida [All files] sektsioon. Parempoolsesse kasti lisada read “-lprintf_flt„ ja “-lm„. [Linker Options] sektsiooni lisada rida “-uvfprintf„.

3. Vajutada OK ja sulgeda seadete aken.

KontrollerLab for Linux

The following guide describes the installation and use of the AVR toolkit 9:10 Ubuntu operating system.

Software Installation

Install the following software:

1. Linux software packages

  • gcc-avr – GNU C-language compiler for AVR
  • avrdude – Program for uploading hex-files to microcontroller
  • avr-libc – C language libraries to write code for AVR platform

To install the packages, use the terminal command:

sudo apt-get install gcc-avr avrdude avr-libc

or graphical installation software (such as Ubuntu software center or Synaptic packet manager).

2. HomeLab library

The library simplifies the writing of program code, since lower-level functions are ready-made. Visit the HomeLab website and download the file named Homelab library vX.X.run, where XX represents the version number. Run the following command to install the library:

sudo sh homelab_library_vX.X.run

Make sure that your library installation is successful.

3. KontrollerLab

KontrollerLab is an IDE (integrated development environment) for writing, compiling, loading and debugging AVR software. Download the KontrollerLab software and save it to some folder (for example, ~/Documents/AVR/KontrollerLab). Run the following command in this folder:

sudo dpkg -i kontrollerlab*.deb

If you have problems with packet dependencies, run the command which installs the missing packages:

apt-get install –f

Connecting the programmer

Connect to programmer with computer and see if the computer recognizes it. Write the command „lsusb“ in the terminal window which should show the list of connected USB devices. Programmers name is „Future Technology Devices International, Ltd FT 232 USB-Serial (UART) IC“.

To get the port to which the programmer is connected to, check the /dev folder using the commands cd /dev (sets /dev as a current folder) and dir (displays the content of the folder). As the programmer is USB-serial interface, it is named as a „ttyUSBx“ where „x“ marks the index of the inteface. If there are no other USB-serial devices this number is zero.

Creating a new project

To write an AVR program, a project must be created which contains all the necessary files: source codes, header files, compiled program, etc. To clearly seperate projects, a folder for each project should be made (this option is also given by the project wizard).

To create a project follow the steps:

1. Open KontrollerLab (Applications → Programming → KontrollerLab) and start a new project from the File → New → New project menu . A window opens where the project location must be specified. In this example the locations is ../Homelab/blinkingLED/.

2. The project must have at least one C file where to write the program code. Files can be added from the File → New → New menu. In the opening window, select C source as a file type and specify the name of the file.

3. Next, the project must be configured for HomeLab kit. From the Project → Configure Project menu open the configurations window and select Common tab. CPU type should be ATmega128 and the clock should be 14745600,0 Hz. Also the names of the HEX and MAP files should be specified. Pressing a Set as default button makes these configurations as a default for new projects. This is reasonable when working only with HomeLab AVR microcontroller. As the HEX and MAP files are also stored as a default it is recommended to use some general name for them, for example „out.hex“.

NB! As the HomeLab library can not be added on the Linker configuration tab, the command “-lhomelab„ must be added behind the name of the MAP file.

Apply settings on the Compiler tab as shown on the following screenshot. Before pressing OK set compiler configurations also as a default.

4. Configure the programmer by opening the configurations window from the Project → Configure Programmer menu. Choose „AVRDUDE“ as a programmer. On the „AVRDUDE“ tab set the programmer type to jtagmkI and connection port to /dev/ttyUSBx (where „x“ is the port index). Set these configuration settings also as a default.

5. At last, place the windows in the KontrollerLab as it is more convenient and get ready to write your first program.

Writing and testing a program

After the configurations steps are done, it is time to programm.

1. Connect the programmer with Controller module. Double-check if the programmer is correctly connected with a JTAG socket. The cable must head away from the board (look at the picture). Now connect the power supply and check if the green LED lights on the Controller board.

2. Write the following program in the Kontrollerlab file editor window and compile it:

#include #include

int main(void) {

// Set pin PB7 as an output
DDRB = 0x80;

Lõputu tsükkel while (true) { Inverting pin PB7

	PORTB ^= 0x80;
	hw_delay_ms(500);
}

}

Toolbar

Make sure that the output window shows „File compiled successfully“ message. If the „Error(s) occurred: “ message is shown, check the program code for mistakes.

3. To download the program into the Controller press the Ignite button. After the succeful download, the „Project built and uploaded successfully“ message should be shown.

If everything was done correctly the red LED on the Controller board should blink periodically, with 1 second interval.

Using floating-point numbers

Sometimes it is neccessary to use floating-point numbers in program. To calculate with them and use them with printf-typed functions, some modifications in project configuration must be done:

1. Open the Project Configurations window and the Linker tab. Check the first line in the Linker flags list (look at the picture).

2. Press OK and close the window.

 

User Interface

Järgnevad peatükid tutvustavad erinevaid komponente, mis on mõeldud mikrokontrolleri ja inimese vaheliseks suhtluseks. Lihtsamaid komponente nagu valgusdioode ja lüliteid saab juhtida mikrokontrolleri digitaalsete sisend-väljundviikude funktsioonidega. Viigud on mikrokontrolleri metallist kontaktid, kõnekeeles jalad, mille kaudu saab edastada ja vastu võtta digitaalseid signaale. Kui viik seadistada programmis sisendiks, saab selle kaudu mikrokontrollerisse lugeda lülitite või muude lihtsamate andurite olekut. Kui viik seadistada väljundiks, saab selle kaudu süüdata valgusdioode või juhtida elektriseadmeid. Keerukamad seadmed nagu ekraanid ja heligeneraatorid ei toimi pelgalt enam lihtsate digitaalsete signaalidega vaid vajavad suhtluseks, kas mingit andmevahetuse protokolli rakendamist või erineva kujuga digitaalsete impulsside genereerimist.

Peaaegu kõigi tüüpiliste mikrokontrollerite viigud võimaldavad lihtsaid sisend-väljundfunktsioone täita, kuid tavaliselt on neil viikudel ka alternatiivfunktsioonid. Enne alternatiivfunktsioonidega tegelemist, tuleks aga lihtsamad funktsioonid endale selgeks teha.

 

Light-emitting Diode

Theory

5 mm legged LED

A light-emitting diode is a semiconductor which emits light when forward voltage is applied. The acronym for light-emitting diode is LED. There are different color combination of diodes and the diodes, which can also emit white light. Like a normal diode, the LED has two contacts – anode and cathode. On drawings the anode is marked as “+” and cathode as “-“.

Schematic symbol of LED and it's polarity

When forward voltage is applied, an LED’s anode is connected to the positive voltage and the cathode to the negative voltage. The voltage of the LED depends on the LED’s color: longer wavelength (red) ~2 V, shorter wavelength (blue) ~3 V. Usually the power of a LED is no more than a couple of dozen milliwatts, which means electrical current must be in the same range. When applying greater voltage or current a LED may burn out.

If the LEDs are used specially to illuminate, it is wise to use special electronic circuits which would regulate current and voltage suited for LEDs. However LEDs are quite often used as indicators and they are supplied directly from microcontroller’s pins. Since the supply voltage for microcontrollers is usually higher than the voltage for LEDs, there must be a resistor connected into series with the LED, which limits current and creates the necessary voltage drop. Instructions to calculate proper resistor can be found in the electronics chapter.

LEDs are produced in a variety of casings. Most common LEDs with feet have 3 mm or 5 mm diameter round shell and two long metal connector pins. Longer pin is the anode, the shorter one is the cathode. Surface mounted casing LEDs (SMD – Surface Mounted Device) have a T-shaped symbol on the bottom to indicate the polarity, where the roof of T stands for the location of the anode and the pole marks the cathode.

Polarity of legged and SMD LED's

HomeLab Practice

The HomeLab controller control module has one single indicator LED, whose anode is connected through resistor to a power supply and the cathode is connected to the controllers pin. In order to switch on and off this LED, LED pin should be defined as the output and set low or high accordingly. Which means if the pin is set high, the LED is turned off and if the pin is set low, the LED is turned on. Basically it would be possible to connect the LED also so that the anode is connected to the pin of microcontroller, and the cathode is connected to the earth (somewhere there has to be a resistor too) – in that case when the pin is set as high, the LED shines and when the pin is set as low the LED is switched off.

All practical examples for the HomeLab kit, LED switching included, use HomeLab’s pin library. Pin library includes data type pin, which contains addresses of pin related registers and pin bitmask. If to create a pin type variable in the program and then initialize it by using macro function PIN, the pin can be used freely with this variable (pin) through whole program without being able to use registers. Here are 2 example programs, which are doing exactly the same thing, but one is created on the basis of HomeLab’s library, the other is not. The debug LED, led_debug in HomeLab library, has been described as PB7 (HomeLab I & II) and PQ2 (HomeLab III). The Debug LED is physically located in the Controller module.

HomeLab Controller module LED test program, which is based on HomeLab library #include

LED pin configuration. pin led_debug = PIN(Q,2); Main program int main(void) {

// Configuring LED pin as an output
pin_setup_output(led_debug);
	
// Lighting up LED
pin_clear(led_debug);	

}

HomeLab II Controller module LED test program, which accesses registers directly #include

Main program int main(void) { Configuring LED pin as an output

DDRB |= (1 

Switch

Theory

A switch is an electromechanical device which can connect or break an electrical circuit. There are many different types of switches; the most common mechanical switch is mechanically connectible electrical connectors. If connectors are connected, electrical circuit is closed and electricity can flow through the switch. If connectors are disconnected, electricity cannot flow through the switch.

Switches are commonly used to electrify electrical circuits, but can also be used as sensors. Switch as a sensor is also the subject of this exercise and therefore examining specific high-voltage and high-amperage switches has been excluded. Switches can be differentiated by the number of contacts and by their connection method. Different types include: two contact switches and double switches, where contact pairs are connected, but also push button, sliding, rocker and toggle switches as well as switches which disconnect instead of connect electrical circuit.

Different schematic symbols are used for identifying different types of switches. Below are examples of typical electrical switches used in electrical drawings with their symbols:

Push button switch Toggle switch Rocker switch Micro switch DIL switch

In order to use a switch as a sensor connected to a microcontroller, one contact of the switch is connected to the microcontrollers pin and is set as input in the program. If contact is connected to the ground or input potential, the bus’s bit rate of microcontroller’s pin is changed. It would sound logical to use toggle switch, which allows connecting one contact with desired contact (in this case ground or input). For our purpose it is not as simple, since on the moment of shifting of the connections the contacts are not connected. The moment itself is very short (milliseconds), but during this moment microcontrollers input pin is connected to nowhere and therefore has indefinite value. Due to electromagnetic interference (which exists everywhere) input pin that is connected to nowhere can have a value of 0 or 1 at random moments in time.

Switch connection scheme with pull-up resistor
Bouncing of contacts of a switch

The interferences complicate the usage of switches. Most common method for avoiding the undetermined results is to connect microcontroller’s input to the ground or input potential through a resistor. A resistor for this function is called pull-down or pull-up resistor. Usually the resistance of pull-down or pull-up resistor varies from 1 kΩ to 1 MΩ. With open switch, the input is charged with voltage of the resistor, by closing the switch, the input receives the voltage of the switch since the resistivity of the switch is a lot smaller (close to zero) compared to the one of the resistor. Basically it can be referred to as a voltage divider.

A simple two contact switch can be used as a sensor with pull-up or pull-down resistor, switch connects input with one and resistor to the other potential. Usually microcontrollers have built-in pull-up or pull-down resistor option; therefore, there is no need to add a resistor to the circuit. For example, AVR microcontrollers have 20 kΩ – 50 kΩ pull-up resistors on their IO pins.

It must be mentioned that, mechanical switches have one more problem – switch bounce. This causes several very short missconnections at the moment of connection. It must be emphasized, that the examples used in this chapter are not affected by the switch bounce and the issue will be covered in more detail in the next chapter.

Homelab User interface board button test code #include Main program int main(void) {

// Set LED pins as output and switch pins as input
pin_setup_output(led_green);
pin_setup_input(S1);

Endless loop while (1) { green LED turns on when switch S1 is pressed

	if(pin_get_value(S1) == 1)
	{
		pin_set(led_green);
	}
	else
	{
		pin_clear(led_green);
	}
}

}

Filtration of switch bounce
RC-filter of a switch

Main method used for avoiding flickering caused by the bouncing of contacts is filtering. Filtering can be done electrically or by software. To filter electrically the switch must be connected through a low-pass filter – for example a RC filter – witch smoothed changes of voltage and therefore the pin of microcontroller does not have transient values. RC filter is shown on the drawing. Filtering by software is done by assessing the value of the pin where the switch is connected; if the value remains the same at number of times in pre set time limit, it is considered to have a steady position and hence has no flickering problem. However, with each type of filtering a delay factor in defining the status must be taken under consideration.

Several software solutions are used for filtering, this can be performed either easy or complex way both with its advantages and disadvantages. If the program is set to have only few infrequent pressings of the button, a long pause can be set to follow the pressing, this will rule out reaction to the switching caused by bounce. However, while using this solution must be considered – in case the user holds the button down for a long period of time, the program reacts also on the miss witching caused by the release of the button.

A program which controls the state of the switch several times in fixed period of time is more dependable (the longer is the time and the higher is the number of controls performed, the better is the result).

Practice

There are three push button-switches on the User interface module. Those switches connect the pins of microcontroller to the earth, however not directly through a resistor, this is to avoid short circuiting when pressing the button while setting the pins as output. The switches have also pull-up resistors, but those have much greater resistance than protective resistors, therefore while pressing the button, there will still be approximately 0 V voltages on the corresponding pin.

Switch positions are shown in the hardware description. In order to read the status of the switches, the corresponding pins of the microcontroller must be set as inputs. There is no need to put AVR internal pull-up resistors into operation, because the pins already have external resistors. When the button is pressed down, the corresponding bus of the pin has value 0, when the button is released, the value is 1. LED indicators can be used to see if the microcontroller understood the buttons action.

Below is a function for reading filtered values of a button for User interface module:

Function for reading filtered values of a IO extension module unsigned char button_read(pin button) { unsigned char buffer = 0xAA; unsigned char timeout = 100; We wait until the status of the button is celar

// or clearing the state expires
while (timeout-- > 0)
{
	// Having 8 place (bit) bufffer of state
	// All previous states (bits) are shifted to left
	// and a new state(bit) is added to the right
	buffer 

 

Delay

Theory

There is often a need to create delays in programs of microcontrollers, it is necessary to time the actions or wait them to end. By its concept one of the easiest methods for creating a break in the work of a microcontroller is overloading its processor with some alternative action – for example order it to count big numbers. From the stroke frequency of the processor can be calculated to which number it should count in order to get a certain time delay. Counting a number from zero up to the value of the stroke frequency of the processor in hertz-s, should theoretically create a delay for one second. For number of reasons this is not as simple in practice.

If the processor of the microcontroller calculates using numbers which’s binary form is as wide as its inner bus (AVR has 8 bits), then it takes one firing stroke of the processor to perform one arithmetical operation for example adding 1 to any value. In order to operate with thousands or millions the number has to be 16 or 32 bit and for an 8 bit processor it takes more than one firing stroke to calculate them. Hence when dealing with large numbers, one has to be familiar with the inside of the processor – exactly its commands.

When programming in advanced languages (C-language for example), the programs are not written directly on the basis of the command, in order to create a software delay, one needs to know also its compiler which converts the program to the machine code. From this depends how many instructions (and phases therefore) it takes to perform one arithmetical operation. Complexity is added by compilers ability to convert the program into the machine code in several ways – for example, by making the machine code as memory saving as possible or easily executable. Such compiler’s actions are called optimization. With different modes of optimization the software delay’s machine codes and their duration come out different.

Practice

The following is an example of generating software delay with AVR microcontroller. A part of a program in C-language is written, which counts the variable x of for-cycle from 0 to 100. Inside each cycle a no-action empty instruction is completed. It is needed, because if the content of the cycle is empty, the compiler optimizes it out of the program as it considers this to be useless.

unsigned char x;

Cycle until x is 100 for (x = 0; x < 100; x++) { With empty instruction nop

asm volatile ("nop");

}

This is the same part of a program after compiling. 2 hexadecimal numbers on the left is machine code and on the right is the command with operand(s) in assembler language. The machine code and the assembler language are conformal; the assembler is just for presenting the machine code for humans in a readable form. In compiling, the optimization of the length of the program is used (compiler’s parameter –Os).

80 e0 ldi r24, 0x00 ; r24 loading number 0 to the index 00 00 nop ; Empty operation 8f 5f subi r24, 0xFF ; subtracting 255 form the r24 index, that means adding +1 84 36 cpi r24, 0x64 ; comparing r24 index with number 100 e1 f7 brne .-8 ; If the comparison was wrong, then transfer 8-baits back

In the compiled form can be seen, what is actually happening with the cycle of the C-language and it can be used to calculate how many clock sycles is needed to complete a cycle of one period. The information about the effect of the instructions and operating time can be found from AVR’s instructions datasheet. In the given example, it takes 4 clock cycles to complete 4 instructions in one cycle period, because all instructions demand one clock rate. In addition, one clock rate is used before the cycle for loading instruction and afterwards one extra clock rate for exiting the cycle. By assuming, that the working clock rate of the controller is 14,7456 MHz, the whole delay produced by the program can be calculated.

(1 + 100 ⋅ 4 + 1) / 14745600 = 27,26 μs

The delay produced in the example, is in microseconds and the variable used is 8-bit so the machine code is fairly simple. In order to produce a break in millisecond, we need to count much larger numbers and thus the machine code gets longer. Cycles working inside each other may also be used, but with this method the delay is not in linear relation with the number of the cycles because with each level of cycle a small extra delay occurs.

The goal of this exercise is not creating precise software delay on the level of machine code, because it is quite an accurate work and we already have the functions necessary to produce delays in the avr-libc and in the library of the HomeLab. Those are used also in the following examples.

When dealing with the software delay it is important to know, that regardless its basic simplicity; it is extremely inefficient method from the power consumption point of view. During all of these clock rates when the microcontroller is counting the useless, energy is consumed. So if using applications operating on batteries, it is not wise to write long software delays. Wiser is to use hardware timers, which are working independently and wake the processor from hibernating when it is time to continue the work.

The software delay is not the only method for creating breaks. The same can be done using timer. Timer is a hardware which counts up or down with a certain frequency. The clock frequency of the timer can be generated from microcontroller’s frequency or from some kind of other outside pace. In general the clock frequency can be divided with a multiplier to reach a smaller frequency - this is done with prescaler. Important fact is that the fixed clock frequency timer’s value is linearly related to the time. The time can be calculated by multiplying the period of the clock frequency of the timer with the value of the timer.

The events which come with the changes of AVR timer.

AVR counters can be made to inform about overflow of the counter or achieving compare mach. Overflow happens when the counter has the maximal possible value and the cycle starts all over again form 0. With reaching a pre set value during the moment of growth of the counter’s value it is compared to the value given by the user. On the occurrence of the event, the bits in the status indexes of the AVR are automatically set as high.

For generating a delay using a timer, it is only necessary to set the timer and waiting for the status bit to go high. Different from the software delay, the work of the timer is not depending on the compiler, which makes them more reliable. At the same time the diversity (or complexity) of the set-up of the AVR counter can be considered fairly troublesome. Depending on the microcontroller’s timing signal, may happen that it will not divide exactly with the desired delay period and the delay will not be accurate.

The following code of a program is about software delay function sw_delay_ms , which makes a given delay in milliseconds using the parameter count. The function uses avr-libc library’s function _delay_ms which is partly written in assembler language. The reason why the _delay_ms is not used in this exercise immediately is that when using the _delay_ms problems may occur when the delays are long. The sw_delay_ms enables creating 65535 ms long delays without any complications.

Software delay in milliseconds void sw_delay_ms(unsigned short count) { Counting the variable of the delay to 0

while (count-- > 0)
{
	// 1ms delay with a special function
	_delay_ms(1);
}

}

The following program is for using the given function, this creates two delays in the endless loop: 100 ms and 900 ms. During the shorter delay LED is lit and during the longer it is switched off, the result – the LED is blinking periodically

The demonstration program of the software delay of the HomeLab The program is blinking a LED for a moment after ~1 second #include #include

Main program int main(void) { Setting the pin of the LED as output

pin_setup_output(led_debug);

Endless loop while (true) { Lighting the LED

	pin_clear(led_debug);

Software delay for 100 ms sw_delay_ms(100); Switching off the LED

	pin_set(led_debug);
	// Software delay for 900 milliseconds
	sw_delay_ms(900);
}

}

Although it seems that the LED blinks in every 1 second, the time is actually a little bit longer, because the callouts of LED’s and delay functions are taking a couple of clock rates of the microcontroller

The program code below is a delay function based on a timer, which is simplified a little bit. The principle of counting is the same as it is at software delay function – a desired amount of 1 ms long delays are produced. The delay is produced with an 8-bit counter 0. It is calculated previously that at clock frequency 14,7456 Mhz the timing signal has to be divided at least 64 times, so that the counter would not reach to overflow in 1 ms. The value which the counter must have so that the overflow occurs after 1 ms is presented in the form of an expression and the variable is timer_start. F_CPU which is a constant in macro-language, that shows clock frequency in Hz. The clock frequency should be 25,6 at the moment but since fractions can not be used, the initial value will be set 26. Unfortunately here arises a mistake in delay time, however it is fairly small (-1,7 μs).

In the cycle takes place initialing of the counter and zeroing the flag of the overflow (by writing 1 into that). Then is waited until the counter counts to 256 from the initial value, i.e. to the overflow. At the moment of the overflow the flag goes high and the delay of 1 ms has taken place. In the end of the function the timer is stopped.

Hardware delay in milliseconds void hw_delay_ms(unsigned short count) { Calculating the initial value of the timer

register unsigned char timer_start = 256 - F_CPU / 1000 / 64;

// Starting the timer
timer0_init_normal(TIMER0_PRESCALE_64);
// Counting the variable of the delay to the 0
while (count-- > 0)
{
	// Initializing the timer
	timer0_set_value(timer_start);
	// Zeroing the overflow flag
	timer0_overflow_flag_clear();			
	
	// Waiting for overflow
	while (!timer0_overflow_flag_is_set())
	{
		asm volatile ("nop");
	}			
}
// Zeroing the overflow flag
timer0_overflow_flag_clear();	
// Stoping the timer
timer0_stop();	

}

Referenced delay function uses a timer library whose source code for ATmega controller looks like the following:

Timer 0 prescaler selection type typedef enum { TIMER0_NO_PRESCALE = 0x01, TIMER0_PRESCALE_8 = 0x02, TIMER0_PRESCALE_32 = 0x03, TIMER0_PRESCALE_64 = 0x04, TIMER0_PRESCALE_128 = 0x05, TIMER0_PRESCALE_256 = 0x06, TIMER0_PRESCALE_1024 = 0x07 } timer0_prescale; Setting Timer 0 to a normal mode inline void timer0_init_normal(timer0_prescale prescale) {

TCCR0 = prescale & 0x07;

}

Stopping the Taimer 0 inline void timer0_stop() { TCCR0 = 0x00; } Taimer 0 value set inline void timer0_set_value(unsigned char value) {

TCNT0 = value;

}

Timer 0 overflow flag clear inline void timer0_overflow_flag_clear(void) { bit_set(TIFR, TOV0); } Timer 0 overflow flag state reading inline bool timer0_overflow_flag_is_set(void) {

return (bit_is_set(TIFR, TOV0) ? true : false);

}

The following is a similar program to the example of the software delay. In the shorter 100 ms half-period the LED is lit and on the longer 900 ms half-period it is switched off. As the result the LED is blinking after every second. Unfortunately, in this example the period isn't precisely 1 second either, because executing other functions of the program takes also time. For exact timing a 16-bit timer with interruptions must be used.

Demonstration program of hardware delay of the HomeLab The Program blinks LED for a moment after every ~1 second #include #include

Main program int main(void) { Setting the pin of the LED as output

pin_setup_output(led_debug);
// Endless loop	
while (true)
{
	// Lighting the LED
	pin_clear(led_debug);

	// Hardware delay for 100 milliseconds
	hw_delay_ms(100);
	// Switch off of the LED
	pin_set(led_debug);
	
	// Hardware delay for 900 milliseconds
	hw_delay_ms(900);
}

}

 

7-segment LED display

Theory

7-segment

7-segmented LED number-indicator is a display which consists of 7 LEDs positioned in the shape of number 8. By lighting or switching off the corresponding LEDs (segments), it is possible to display numbers from 0 to nine as well as some letters.

Electrically all anodes of the LEDs are connected to one anode pin ca. LEDs are lit by switching their cathodes (a, b, c…). Exists also reversed connections, where the indicators have a common cathode cc. Generally several number-indicators are used for displaying multi digit numbers - for this purpose the indicators are equipped with coma (point) segment dp. All in all one indicator has 8 segments, but they are still called 7-segmented according to the number of number-segments.

Positioning of the LED indicator's segments and electrical scheme
The build-up of the LED driver's shift-index with corresponding segments of the indicator.

LED number-indicators are easy to use, they can be controlled directly from the pins of the microcontroller, but there are also special drivers, which able to control number-indicators using fewer pins of the microcontroller. There are different colors of LED number indicators, which can be very bright and very large. For displaying the entire Latin alphabet exist indicators with extra segments. There are different drivers, but common drivers using a serial interface, which is similar to the SPI, where both clock signal and data signal are used. Different from SPI the chip-select is not used there, and is replaced with latch function. The above mentioned three lines are connected to the controller pins.

  • Latch-signal
  • Clock-signal
  • Data-signal

Practice

There is one 7-segment LED number-indicator on the Digital i/o module. It is controlled through a driver with serial interface. For displaying the numbers on the HomeLabs Digital i/o module indicator, the following functionality is written to the library of the HomeLab.

Marking card The bits are marking the segments. Lower ranking is A, higher ranking is DP const unsigned char attribute [2] segment_char_map[11] = {

0b00111111,
0b00000110,
0b01011011,
0b01001111,
0b01100110,
0b01101101,
0b01111100,
0b00000111,
0b01111111,
0b01100111,
0b01111001   // E like Error

};

Start-up of the 7-segment indicator void segment_display_init(void) { Set latch, data out and clock pins as output

pin_setup_output(segment_display_latch);
pin_setup_output(segment_display_data_out);
pin_setup_output(segment_display_clock);

}

Displaying number on the 7-segment indicator void segment_display_write(unsigned char digit) { unsigned char map; signed char i; Check-up of the number

if (digit > 9)
{
	digit = 10;
}

// Number as the card of the segments
map = segment_char_map[digit];

Latch-signal off pin_clear(segment_display_latch); Sending he bits. Higher ranking goes first

for (i = 7; i >= 0; i--)
{
	// Setting the pin according to the value of the bit of the card
	pin_set_to(segment_display_data_out, bit_is_set(map, i));

The clock-signal as high for a moment pin_set(segment_display_clock); _delay_us(1); The clock-signal as low

	pin_clear(segment_display_clock);
	_delay_us(1);
}

Latch-signal on pin_set(segment_display_latch); } For displaying numbers and the letter “E”, is created a „weak“ constant array segment_char_map, where lighting of all 8 segments is marked with bit 1 and switch off is market with bit 0. The bits form lower to higher (from right to left in binary form) are marking segments A, B, C, D, E, F, G ja DP. The control interface of the driver is realized through software SPI, i.e. by using a software for controlling the data communication pins in the program. All three pins are set as output with segment_display_init function. segment_display_write is for displaying the function, which finds the segment-card of the mark from the array and transmits bit by bit all values of the segments to the driver. The frequency of the clock signal with the software delays is now approximately 500 kHz. When a user defines a variable segment_char_map its own code, it is possible to create other characters on the screen (eg, text, etc.) The following is a more concrete example of a program for using the number-indicator. Previously described function of the library is described in the program. The program counts numbers from 0 to 9 with approximate interval of 1 second and then displays letter E, because two-digit numbers is not possible to show on the one digit indicator. The example program of the 7-segment LED indicator of the HomeLab's #include #include

Main program int main(void) { int counter = 0; Set-up of the 7-segment indicator

segment_display_init();
// Endless loop
while (true)
{
	// Displaying the values of the counter
	segment_display_write(counter % 10);
	// Counting up to 10
	counter++;
	if (counter>19) counter=0;
	// Delay for 1 second
	sw_delay_ms(1000);
}

}

 

LCD screen

Theory

The graphical LCD element
The picture formed of pixels of a graphic LCD

LCD screens, which are used with microcontrollers, can be divided mainly into a two parts: a text or alphanumeric LCD and a graphic LCD. Alphanumeric LCD is liquid crystal display, with the purpose of displaying letters and numbers. In basic LCD is used liquid crystal which is placed between transparent electrodes, and which changes the polarization of the passing light in electrical field. The electrodes are covered by polarization filters, which assure that only one way polarized light can pass the screen. If the liquid crystal changes its polarity due to an electrical field, the light can not pass the screen or part (segment) of it and it looks dark.

Main characteristic of alphanumerical LCD is the placing of its segments. The screen is divided into many indicators. Each indicator has either enough segments for displaying letters and numbers or it is formed from matrix of little square segments (pixels). For example, a matrix of 5×7 pixels is enough to display all numbers, and letters of Latin alphabet. There are usually 1 – 4 rows of indicators and 8 – 32 columns. Each indicator has a small difference similar to the differences of the letters in text.

Besides the screen Alphanumerical LCD has also controller which controls the segments of the screen according to the commands from the communication interface. A controller has a preprogrammed card of letters, where each letter, number or symbol has its own index. Displaying the text on the screen is basically done by sending the indexes to the controller. In reality there must be more control orders sent to the controller before anything can be displayed. It is important to get familiarize with each LCD data-sheet, because there are many different types of LCDs and they all are controlled differently.

Graphical LCD liquid crystal display is a display which allows displaying pictures and text. Its construction is similar to the alphanumerical LCD, with a difference that on the graphic display all pixels are divided as one large matrix. If we are dealing with a monochrome LCD, then a pixel is one square segment. Color displays’ one pixel is formed of three subpixels. Each of the three subpixels lets only one colored light pass (red, green or blue). Since the subpixels are positioned very close to each other, they seem like one pixel.

Monochrome graphic displays have usually passive matrix, large color displays including computer screens have active matrix. All information concerning the color of the background and the pixels of the graphic LCDs are similar to alphanumerical LCDs. Similar to the alphanumerical displays, graphic displays are also equipped with separate controller, which takes care of receiving information through the communication interface and generates the electrical field for the segments.

Practice

In the HomeLab III set is a 128×160 pixels and 1,8 inch full color TFT LCD screen. Sitronixi ST7735 controller is attached to the display which can be communicated through SPI serial interface. The background lighting of the display module is separately controlled, but without the background light, it is not possible to use the screen. Communicating with the display is not very difficult, but due to the large amount of the functions it is not explained here. Home-Labs library has functions for using it.

Main difference compared to from HomeLab III to HomeLab II is a 84×48 pixels monochrome graphic LCD. It is the same display as used in Nokia 3310 mobile phones. Philips PCD8544 controller is attached to the display which can be communicated through SPI-like serial interface. The background lighting of the display module is separately controlled.

First, the graphical LCD screen must be started with lcd_gfx_init function. There is a letter map in side of the library with full Latin alphabet, numbers and with most common signs written. To display a letter or text, first its position must be determined by using function lcd_gfx_goto_char_xy. For displaying s letter is lcd_gfx_write_char function and for displaying text lcd_gfx_write_string function.

The following is an example of time counter. The program counts seconds (approximately), minutes and hours. For converting time to text sprintf function is used.

Example of using the graphic LCD of the HomeLab Time of day is displayed on LCD since the beginning of the program #include #include #include

Main program int main(void) { int seconds = 0; char text[16]; Set-up of the LCD

lcd_gfx_init();
// Cleaning the screen
lcd_gfx_clear();
// Switching on the background light
lcd_gfx_backlight(true);	
// Displaying the name of the program
lcd_gfx_goto_char_xy(1, 1);
lcd_gfx_write_string("Time counter");
// Endless loop	
while (true)
{
	// Converting the seconds to the form of clock
	// hh:mm:ss
	sprintf(text, "%02d:%02d:%02d",
		(seconds / 3600) % 24,
		(seconds / 60) % 60,
		 seconds % 60);
	// Displaying the clock text
	lcd_gfx_goto_char_xy(3, 3);
	lcd_gfx_write_string(text);
	
	// Adding one second
	seconds++;
	
	// Hardware delay for 1000 ms
	hw_delay_ms(1000);
}

}

Periodic interrupt

Theory

The goal of this chapter is to demonstrate the usage of the interrupts on the example of the counters. The interrupts are program parts which are reacting to the events taking place in the microcontrollers. They are usually used for quick response to an event, but they can also be used for completing several parallel processes, precisely timed action and saving power. For example, it is possible to make a LED blinking using interruptions, so that blinking frequency does not depend on what is happening in the program at the moment. When the interrupt occur then main program execution stopped and the interrupt priority check of the interrupt vector table happen, after that the program of the interrupt function has been executed. While the interrupt program will be executed then the main program execution continues on the state where it left off.

Practice

The following program shows how the counter is set up to make an interrupt. There are 2 LEDs of the Digital i/o module in the program, the state of the red LED is changed periodically with software delay, the state of the green LED is changed when interrupts occur. There is a separate exercise for blinking LED with software delay and it is not explained here. The main goal is to explain the usage of the library of the counters and interrupts.

The following shows the use of interrupts of the xmega controller. In the beginning of the program, the 16-bit counter/timer E1 has been set up. First, the timer period will be set, so the maximum value of the count function TC_SetPeriod. The divider of the counter is 1024 and the value of period is 31249, so when the clock frequency is 32 MHz, the period will be exactly one second. It is easy to calculate with following formula:

period = (32000000 Hz / 1024 / 1) - 1 = 31249

After allowing the interrupt to achieve the maximum value of the counter 1, an interrupt must be allowed at the global level, which means over the entire microcontroller. The global interrupts can be enabled by function sei and forbidding with cli. A header file avr/interrupt.h must be included for defining the program part of these functions and interrupts. The program part of the interrupt is defined with macro function ISR, which parameter is the name of the interrupt vector. In this set-up the vector of counter 1’s maximum value achievement interrupt is TCE1_OVF_vect. In addition, to allow the global interrupt, a different priority interrupts should be enabled one by one, using the xmega PMIC.CTRL register.

HomeLab III example of blinking LED with counter interrupt #include #include #include #include Interruption ISR(TCE1_OVF_vect) {

// Changing the state of the green LED
pin_toggle(led_green);

}

Main program int main(void) { Setting the pins of the LEDs as outputs

pin_setup_output(led_green);
// Setting the period of timer E1
// F_CPU/1024/[aeg] - 1 = periood
// 32000000 / 1024 / 1 - 1 = 31249
TC_SetPeriod(&TCE1, 31249);
// Setting the clock of timer E1 (F_CPU/1024)
TC1_ConfigClockSource(&TCE1, TC_CLKSEL_DIV1024_gc);
// Setting timer E1 to the normal operating mode
TC1_ConfigWGM(&TCE1, TC_WGMODE_NORMAL_gc);
// Enabling high-priority overflow interruptions
TC1_SetOverflowIntLevel(&TCE1,TC_OVFINTLVL_HI_gc);
// Enabling high-priority interruptions
PMIC.CTRL |= PMIC_HILVLEN_bm;
// Enabling global interruption
sei();
// Endless loop
while (1) { }

}

Example of interrupt is quite different between ATmega series (in this example ATmega2561) controllers, because the timers, compared to the xmega series controllers, are also different.

In the beginning of the program, the 16-bit counter/timer 1 has been set up with the function timer1_init_ctc. With this function the counter CTC clear timer on compare match has been set to the mode where the maximum value of the timer is not 216 - 1 but can be selected. In this case the maximum value is set to equal the value of the ICR1 index. The divider of the counter is 1024 and the value of ICR1 is 14400, so when the clock frequency is 14,7456 MHz, the period will be exactly one second. It is easy to calculate with following formula:

f = 14745600 Hz / 1024 / 14400 = 1

The HomeLab II example of blinking LED with counter interrupt #include #include #include #include Interruption ISR(TIMER1_CAPT_vect) {

// Changing the state of the green LED
pin_toggle(led_green);

}

Main program int main(void) { Setting the pins of the LEDs as outputs

pin_setup_output(led_green);
// Seting the timer up in the CTC mode	
timer1_init_ctc(
	TIMER1_PRESCALE_1024,
	TIMER1_CTC_TOP_ICR);
// The maximal value of the timer is 14400, which
// makes the length of the period 1 s
// Formula: 14,7456Mhz / 1024 = 14400
timer1_set_input_capture_value(14400);
// Allowing interruption of achieving the value
timer1_input_capture_interrupt_enable(true);
// Allowing global interruption
sei();
// Endless loop
while (1){ }

}

At the start of the program it is seen that regardless of what the microcontroller is doing in the main program, the interrupts are taking place and the green LED is blinking.

 

Sound Generator

Theory

Piesoheligeneraator
Kõlar

Taimerite üheks praktiliseks rakenduseks on heligeneraatori või kõlari juhtimine. Heligeneraator on tihti kasutusel juhtpaneelides, alarmseadmetes ja mujal nupuvajutuste või signaalhelide kuuldavaks toomiseks. Sellist heligeneraatorit kutsutakse tihti lihtsalt kõlariks, piiksujaks, või siis buzzeriks, mis on üle võetud inglise keelest. Tööpõhimõttelt võib heligeneraatorid jagada kaheks: piesoelektrilisteks ja elektromagnetilisteks.

Piesoelektriline heligeneraator koosneb metallplaadist ja sellele kinnitatud piesokeraamilisest materjalist elemendist. Piesokeraamiline element muudab vastavalt pinge suurusele oma mõõtmeid, mille tagajärjel metallplaat paindub. Rakendades heligeneraatorile nelikantsignaali või vahelduvvoolu tekib võnkumine ehk heli.

Elektromagnetiline heligeneraator sarnaneb oma tööpõhimõttelt valjuhääldile ehk kõlarile. Ka siin on magnetväljas pool, mille kohale on paigutatud metallist membraan. Kui lasta helisageduslik vool läbi pooli, hakkab membraan tekkiva magnetvälja ja püsimagneti välja koosmõjul liikuma. Analoogselt piesoelektrilisele heligeneraatorile tekib heli.

Üldiselt on piesoelektrilised heligeneraatorid võrdluses elektromagnetilistega suurema helirõhu, väiksema voolutarbe ja kõrgema võimaliku helisagedusega. Kõige tugevama heli kõige väiksema voolutugevuse korral saab siis, kui heligeneraator töötab oma resonantssagedusel. Sellisel juhul on membraani amplituud kõige suurem. Elektromagnetiline heligeneraator ehk kõlar omab võrreldes piesoelektrilise heligeneraatoriga oluliselt paremat tonaalsust ja sobib lisaks lihtsate signaalhelide genereerimiseks ka muusika ja kõne edastamiseks.

Kõlarite juhtimiseks ei piisa tavaliselt digitaalväljundist vaid vaja on analoogsignaali. Selleks on kõige mugavam rakendada digitaal-analoog muundurit (inglise keeles digital-analog converter, lühend DAC). Digitaal-analoog muundur töötab vastupidiselt analoog-digitaal muundurile ja võimaldab mikrokontrolleril tekitada ka analoogväljundsignaali. Odavamatel ja lihtsamatel mikrokontrolleritel (sh ka ATmega128 ja ATmega2560) ei ole digitaal-analoog muundurit kiipi integreeritud. Sellisel juhul võib kasutada välist eraldiseisvat kiipi või tekitada analoogsignaal RC filtri ja võimendusskeemi abil. See nõuab aga mitmeid lisakomponente ja seetõttu on kõlari kasutamine koos mikrokontrolleriga mõnevõrra keerukam võrreldes muude digitaalsignaalidega opereerivate komponentige (nt lülitid, LED-id, andurid, jms).

 

Practice

Kodulabor II Kasutajaliidese moodulil asub piesoelektriline heligeneraator koos võimenduslülitusega. Heligeneraatorit juhitakse viiguga PG5. Heligeneraatori kasutamiseks on Kodulabori teegis olemas funktsioon buzzer_sound, mis toob kuuldavale valitud pikkuse ja sagedusega helisignaali. Heli sagedus antakse ette suhtelistes ühikutes 1-255. Heli kestvus on millisekundites.

Valitud sageduse ja pikkusega helisignaali genereerimine void buzzer_sound (unsigned char freq, unsigned int length) { Heligeneraatori viigu määramine

pin buzzer = PIN(G,5);
// Heligeneraatori viigu väljundiks seadistamine
pin_setup_output(buzzer);
// Timer 0 kiire PWM režiimi seadistamine koos OCR0A ja COM0B1 väljundiga
TCCR0A |= (1 

 

The amplified digital output

Theory

Mikrokontrollerite viigud ei ole tavaliselt mõeldud suurte koormuste lülitamiseks. Atmeli mikrokontrollerite viigud lubavad läbi lasta vaid 30mA viigu kohta, kuid paljudel kontrolleritel on see number veel väiksem (ARM kontrolleritel vaid mõni mA). See tähendab seda, et mikrokontrolleri viiguga saab juhtida vaid madala voolutarbega seadmeid (nt LEDid, mikrokiibid).

N-FET mootori lülitamiseks

Selleks, et juhtida suurema voolutarbega seadmeid on vaja väljundi signaali võimendada. Selleks kasutatakse tavaliselt mõnda transistori või integraalkiipi. Transistori lülitust kasutades tuleks jälgida, et võimendustegud oleks piisav ning ei ületataks maksimaalset viigu- ega transistori voolu.

Üks lihstamaid lahendusi on kasutada väljatransistori (Mosfet). Väljatransistoriks nimetatakse pooljuhtseadist, mille pooljuhist voolu juhtiva kanali juhtivust mõjutab elektriväli ja sellest tulenevalt on ta erinevalt bipolaartransistorist pingega tüüritav element. Väljatransistorid jagunevad ehituselt kaheks: P-siirdega ja N-siirdega (sarnaselt bipolaar-transistoridele PNP ja NPN), lühendatult P-FET ja N-FET.

MOSFETil on tavaliselt 3 viiku: Drain(D), Source(S), Gate(G). Drain viik jääb alati seadme poole, mida soovitakse lülitada, source viik P-FETi puhul + toite, N-FETi puhul GND poole ning gate viiku kasutatakse MOSFETi tüürimiseks. Selleks, et MOSFETi sisse-välja lülitada on vaja tekitada pinge G ja S viikude vahele. Sellest tulenevalt N-FET lülitub sisse, kui G viigul on loogiline 1 (olenevalt MOSFETist on minimaalne pinge 3-14V), ning P-FET lülitub sisse, kui G viigul on loogiline 0. Välja lülitamiseks on vaja MOSFETi G viik viia samale pingenivoole nagu S viik. Seega N-FETi puhul 0V ja P-FETi puhul toitepingeni.

Sellest tulenevalt kui on soov lülitada seadmeid, mille tööpinge on kõrgem juhtelektroonika (nt mikrokontrolleri) tööpingest tuleb kasutada N-FETi, või panna lülitava skeemi ja P-FETi vahele veel üks lisa võimenduse aste,sest muidu ei ole võimalik MOSFETi välja lülitada.

MOSFETi kasutamise eelised võrreldes bipolaartransistoridega on:

  • Kõrge sisendtakistus - lülituse vool on väga väike
  • Madal töötakistus - e. takistus S ja D viikude vahel, MOSFETi soojenemine on võrdlemisi väike
  • Väike temperatuurimõju - lülitatav vool ei sõltu temperatuurist
  • Kõrge lülitussagedus - lülitus on piisavalt kiire, et läbi lasta PWM signaali.
Vastudiood

Aegajalt on vaja lülitada seadmeid, mis peavad olema (või on tungivalt soovituslik, et oleks) elektriliselt täielikult eraldatud lülitavast sekeemist. Näiteks, kui on vaja lülitada vahelduvvoolu seadmeid või väga suure võimsusega seadmeid. Siis tuleks kasutada lülituseks releed. Olenevalt relee mähise lülitusvoolust on vaja mikrokontrolleri viiku ka relee mähise lülitamiseks võimendada kasutades kas bipolaar-transistori või MOSFETi.

Induktiivsete seadmete lülitamisel (nt alalisvoolumootor, relee mähis jne) tuleb kasutada ka kaitsedioodi, mis induktiivse seadme välja lülitamisel oleks võimeline kaitsma lülitusskeemi ja mikrokontrolleriviiku tagurpidi pinge eest. Nimelt tekib induktiivse seadme mähise magnetvälja tõttu negatiivne pinge, mis võib kahjustada kas lülitavat elementi (transistor, MOSFET) või mikrokontrolleri viiku.

Lisaks üksikutele elementidele on aegajalt transistorid või MOSFETid pandud ka ühte integraallülitusse. Üheks näiteks on ULN2004, mis sisaldab endas 7 darlington paari kanalit. Sellise kiibid on ideaalsed juhul, kui on vaja juhtida mitut kanalit (nt unipolaarne samm-mootor), lihtsustades trükkplaadi tegemist ja vähendades üldist komponentide arvu. Tihti on nendesse integraalskeemidesse sisse ehitatud ka vastudioodid.

Practice

Järgmevalt on ära toodud lihtne koodijupp mootori sisse välja lülitamiseks, mis on ühendatud unipolaarse samm-mootori pistikusse. Mootori üks juhe on ühendatud toitega (Vbat) ning teine ULN kiibiga läbi viigu Stp1.

Võimendatud väljundi testkood DC Mootor on ühendatud unipolaarse mootori pistikusse Mootori üsimene viik Vbat Mootori teine viik Stp1 #include

pin motor = PIN(J,3);

Põhiprogramm int main(void) { LEDide ja mootori viigud väljunditeks

pin_setup_output(motor);
pin_setup_output(led_green);
pin_setup_output(led_red);

// Roheline LED kustu, punane põlema
led_on(led_red);
led_off(led_green);
// Lõputu tsükkel
while (true)
{
	// Kui S1 on vajutatud, mootor tööle
	if(button_read(S1))
	{
		pin_set(motor);
		led_on(led_green);
		led_off(led_red);
	}
	// Kui S3 on vajutatud, mootor kinni
	if(button_read(S3))
	{
		pin_clear(motor);
		led_off(led_green);
		led_on(led_red);
	}
}

}

 

Exercises

The goal is to write a program which is able to perform tasks described below.

Warm up exercise

  • By pressing S1 one LED is lit, pressing S2 two LEDs and S3 three LEDs lit.

For beginners

  1. This simulates standard traffic light for cars.
  2. This simulates manually operated traffic light at pedestrian crossing. Until no button is pressed a green LED is lit for the cars. After pressing a button (S1) the green LED will start to blink for 3 seconds, this is followed by lighting the yellow LED for 3 seconds and red for 10 seconds, after this sequence a green LED is lit again. When red LED is on, the 7-segment display countdowns seconds until green LED starts.
  3. This counts how many times the button is pressed. The result is displayed by blinking of the LEDs. After each pressing the number of blinking is increased by one. A random button can be selected. In order for the LED to blink a sub function must be used, with parameters set on the number of blinks.
  4. Present numbers in hexadecimal system randomly on the 7-segment display. The frequency is 1 Hz.
  5. Pressing button S1, the blinking speed of all three LEDs is slowed down two times. Pressing button S3, the blinking gets 2 times faster and pressing button S2 the frequency of the blinking will be set to 1 Hz. Using interrupt is required (do not use software delay).
  6. Create three piece of musics, which will be played when button is pressed. Change the piece of music should be instant when other button is pressed.

For advanced

  1. When pressing buttons in sequence S3 – S2 - S1, green LED will lit. All other combinations results red LED. Every button press a yellow LED will blink.
  2. There is one button for each LED. The controller blinks LEDs randomly and the user has to repeat the same sequence. The sequence of blinks gets longer – one random LED is added with a new round. The sequence is controlled after each user. The time gap between each entry is two seconds. In case of an incorrect entry all LEDs blink three times. (The number of correct entries by the user may be displayed on a LCD screen).
  3. Light in circular sequence 6 outside segments on the 7-segment indicator with the period of 500 ms.
  4. Make a program where you can move “X” symbol around the screen. Use button S1 to move left, button S3 to move right and button S2 to change the row.
  5. Write a simple worm game on the graphic LCD. The width of the worm is 1 pixel and the length is 5 pixels. The worm can be made to turn either left or right using buttons. The worm must be able to avoid collision with the border of the screen (turning before). Bonus points are for ability of picking up the eggs and making the worm to grow. The simplest solution is to make the worm out of the letter “O”.

Questions

  1. What is the difference between operations”=” and”==” ? Give two examples to verify the statement.
  2. What is the difference between operations “|” and “||”? Give two examples to verify the statement.
  3. Write an expression using the equation “x = x + 1” twelve times.
  4. How an endless loop is written in C-programming language? Provide two different examples.
  5. What type of a variable do you choose in C–language to present positive values between 7 and 154?
  6. Witch register determines the direction of a port? Provide an example of configuring settings of ports’ input and output.
  7. What are the methods for eliminating the bouncing of the contacts and the false connections caused by flickering? Provide examples of solutions using both hardware and software.
  8. What is bit shift? Give a practical example with an explanation.
  9. Why are pull-up resistors used in switches? How is their resistance determined?
  10. Calculate the resistance for regulating LED current, the voltage is 5 V, forward voltage of the LED is 2,7 V and the current is 30 mA.
  11. How many pins uses the 7-segment number-indicator (with point segment), if it is connected directly to the controller? How many pins would be needed if if were controlled through the shift register 74HC595?
  12. What determines the brightness of the 7-segment number-indicator? How can it be adjusted if the number-indicator is controlled a)directly b)through the shift register 74HC595?
  13. How can the numbers in decimal system be converted to binary system (to text) and vice versa?
  14. How is monochrome (black and white)LCD different from color LCD?
  15. How is software delay created? On which parameters depends the duration of the software delay?
  16. What makes us use hardware delay/timer with interruptions?
  17. Calculate the overflow interruption period for 8-bit timer, if the clock rate is 16 MHz and frequency divider's factor is 1024.
  18. What can be done with the AVR timers besides counting time?
  19. Which is the longest duration of the interruptions in milliseconds which can be achieved with ATxmega128A1U micro-controller that work at the clock frequency of 32 MHz? Show the calculation formula.
  20. In case the processor is heavily loaded with an execution of a program (for example, it controls several motors and the values of several sensors at once), does this have an effect on the accuracy of the timer? Explain your answer.

Sensors

Sensors

Sensors are devices converting any kind of physical attributes (temperature, luminance, force, acceleration etc.) to a understandable form for humans or machines. With the help from sensors the microcontroller receives information from the surrounding environment and makes decisions based on it. There are many types of sensors, approximately 195 different types are listed in Wikipedia. Only sensors with electrical output signal can be connected to microcontrollers. Based on electrical output signal, is possible to segment sensors as digital and analogue sensors.

In analogue sensor any change in physical attributes changes one of its electrical values, usually voltage, current or resistance. Since microcontrollers are digital devices, the signal have to be converted from analogue to digital before delivering it to controller. For this purpose analogue-digital converters are used which usually are built-in to the microcontroller.

Analogue sensor which already includes digitizer of information, it is called digital sensor. Digital sensors can also standardize information, calibrate sensors and perform a great deal of other functions. There are many ways for transmitting info from digital sensor to microcontroller: the easiest is with logical signals, more complex way – through some data link interface. The following exercises though, are introducing simpler sensors and sensors known in robotics.

 

Potentiometer

Theory

Electric symbol of potentiometer

Potentiometer is a three terminal resistor, witch has fixed resistance between its two side contacts and variable resistance between side and middle contact. In principle a potentiometer is a attenuator (voltage divider), where resistance is formed between side contacts and middle contact.

A typical potentiometer consists of a resistor with conducting surfaces and of a sliding contact called slider. The closer the slider is to the edge of the resistor, the smaller is the resistance between the slider and the edge and vice versa. A material with high resistivity or coil made of resistance wire can act as a resistor. Some potentiometers have linear or logarithmic relations between the resistance and the slider position. Potentiometers are mainly single turn-potentiometers (example on the picture), but exist also slider potentiometers. A special type of potentiometers are digital potentiometers, where the regulation of the resistance is done inside the micro scheme according to the signals.

Practice

Single-turn potentiometer

On the module of the HomeLab is a 10 kΩ turn potentiometer. This potentiometer is connected between ground and microcontroller supply potentials and the slider is connected to the analogue-digital converter (ADC). With this connection, the output voltage of the potentiometer can be regulated between 0 V and microcontroller supply. The digital value of the potentiometer output voltage on its entire adjusting range can be measured if the comparison voltage from AVR digital-analogue converter is taken from AVCC pin. For the Homelab III, the maximum voltage of the AVCC pin is 2.7 V but the inputs can deliver 3.3 volts. The following function for AVR ADC are in the library of the HomeLab:

  • void adc_init(reference, prescale)
  • unsigned short adc_get_value(channel)
  • unsigned short adc_get_average_value(channel, num_samples)

The function adc_init must be called out in the beginning of the program, this is used for making the ADC to work. The reference voltage must be chosen from either AREF pin or AVCC pin, or fixed inner voltage must be selected. In addition the clock cycle of the converter must be set by the prescaler (factor of frequency divider), which will be used to divide the controller clock cycle. The conversion is quicker when using higher clock cycle but with this the accuracy may suffer. Function adc_get_value is for measuring, this able to select the channel and it returns 10 bit (11-bit for Homelab III) results. The function for measuring is inter locking, hence it waits for the end of conversion and returns the results only after all measuring is done.

The following functions of the library are provided to support the ATmega2561 ADC converter.

Starting the ADC void adc_init(adc_reference reference, adc_prescale prescale) { Allowing ADC to operate, selecting the frequency divider

ADCSRA = bit_mask(ADEN) | (prescale & 0x07);

Selecting comparison voltage ADMUX = (reference & 0x03) ==== Thermistor ==== Necessary knowledge: [HW] User Interface Module, [ELC] Voltage Divider, [AVR] Analog-to-digital Converter, [LIB] Analog to Digital Converter, [LIB] Graphic LCD, [LIB] Sensors === Theory === [NTC thermistor] A thermistor is a type of resistor which resistance varies with temperature. There are two types of thermistors: positive temperature coefficient of resistance and negative temperature coefficient of resistance. The resistance of thermistors with positive temperature coefficient of resistance is increasing when the temperature grows and with negative the resistance decreases. The respective abbreviations are PTC (positive temperature coefficient) and NTC (negative temperature coefficient). The thermistors resistances' dependence of the temperature is not linear and this complicates the usage of it. For accurate temperature measurements in wider temperature flotation the Steinhart-Hart third-order exponential equation is used as the thermistors resistance is linear only in small temperature range. The following simplified Steinhart-Hart equation with B-parameter exists for NTC thermistors: The relation between temperature and resistance of a NTC thermistor. where:
* T0 - nominal temperature, usually 25 °C.
* R0 - resistance at nominal temperature.
* B - parameter B. Parameter B is a coefficient, which is usually given in the datasheet of the thermistor. But it is stable enough constant only in a certain ranges of temperature, for example at ranges 25–50 °C or 25–85 °C. If the temperature range measured is wider , the data sheet should be used for retrieving the equation. Usually a voltage-divider is used for measuring the resistance of a thermistor, where one resistor is replaced with a thermistor and the input voltage is constant. The output voltage of the voltage-divider is measured, which changes according to the change of the resistance of the thermistor. If the voltage is applied, current goes through the thermistor which heats up the thermistor due to thermistors resistance and therefore alters again the resistance. The fault caused by heating up of the thermistor can be compensated with calculations, but it is easier to use a thermistor that has higher resistance and therefore heats up less. With restricted resources and with less demands on accuracy, previously calculated charts and tables for temperatures are used. Generally the tables have ranges of temperatures and respective values of resistance, voltage or analogue-digital converters. All exponential calculations are already done and the user needs to only find the correct row and read the temperature given. === Practice === The Sensor module of the HomeLab is equipped with a NTC type thermistor which has 10 kΩ nominal resistance. At temperatures 25-50 °C the parameter B of the thermistor is 3900. One pin of the thermistor is connected to supply and the other one is connected to the analogue-digital converter (HomeLab II channel 2 and HomeLab III channel 14). A typical 10 kΩ resistor is also connected with the same pin of the microcontroller and earth and together with the thermistor forms a voltage divider. Since we are dealing with a NTC thermistor, which resistance decreases as the temperature grows; the output voltage of the voltage divider is increasing repectively with growing temperature. While using the AVR it is practical to use a conversion table of values of temperature and analogue-digital converter to find the correct temperature. It is wise to find corresponding value of analogue-digital converter for each temperature degree of desired range of temperature because reverse table will be too large due to the amount of 10 bit ADC values. It is recommended to use any kind of spreadsheet program (MS Excel, LibreOffice Calc, etc.) to make the table.
Steinhart-Hart formula which is customized for the mentioned NTC thermistors able's to find the resistance of the thermistor which corresponds to the temperature. Derived from the resistance, is possible to calculate the output voltage of the voltage divider and using this output voltage to calculate the value of the ADC. Calculated values can be inserted to the program as follows: Table for converting temperature values to ADC values Every element of the array marks one Celsius degree Elements begin from -20 degree and end at 100 degree There are 121 elements in the array const signed short min_temp = -20; const signed short max_temp = 100; const unsigned short conversion_table[] = { 91,96,102,107,113,119,125,132,139,146,153, 160,168,176,184,192,201,210,219,228,238,247, 257,267,277,288,298,309,319,330,341,352,364, 375,386,398,409,421,432,444,455,467,478,489, 501,512,523,534,545,556,567,578,588,599,609, 619,629,639,649,658,667,677,685,694,703,711, 720,728,736,743,751,758,766,773,780,786,793, 799,805,811,817,823,829,834,839,844,849,854, 859,863,868,872,876,880,884,888,892,896,899, 903,906,909,912,915,918,921,924,927,929,932, 934,937,939,941,943,945,947,949,951,953,955 }; Following algorithm may be used to find the temperature which corresponds to the parameters of the ADC: Converting the ADC values to Celsius degrees: signed short thermistor_calculate_celsius(unsigned short adc_value) {

signed short celsius;
// Covering the table backwards:
for (celsius = max_temp - min_temp; celsius >= 0; celsius--)
{
	// If the value in the table is the same or higher than measured 
	// value, then the temperature is at least as high as the 
	// temperature corresponding to the element
	if (adc_value >= conversion_table[celsius]))
	{
		// Since the table begins with 0 but values of the elements 
		// from -20, the value must be shifted
		return celsius + min_temp;
	}
}
// If the value was not found the minimal temperature is returned
return min_temp;

}

The algorithm searches range from the table where the ADC value is and acquires the lower ranking number of this range. The ranking number marks degrees, adding the primary temperature to this a temperature with accuracy of 1 degree is reached.

This conversion table and function are already in the library of the HomeLab, therefore there is no need to write them for this exercise. In the library the conversion function is named thermistor_calculate_celsius. Must be considered, that the conversion is valid only when used on the thermistor on the Sensors module of the HomeLab. For using other thermistors, a conversion table needs to be created and more complex function described in the manual of the library must be used. Example program of this exercise is a thermometer, which measures temperature in Celsius scale and displays it on an alphabetical LCD.

Example program of the thermistor of Sensors module The temperature is displayed on the LCD #include #include #include #include #include

Robotic Homelab II #define ADC_CHANNEL 2

Robotic Homelab III #define ADC_CHANNEL 14 Main program int main(void) {

unsigned short value;
signed short temperature;	
char text[16];

Initialization of LCD lcd_gfx_init(); Clearing the LCD and setting backlight

lcd_gfx_clear();
      lcd_gfx_backlight(true);
// Name of the program
      lcd_gfx_goto_char_xy(1, 1);
lcd_gfx_write_string("Thermometer");

Setting the ADC adc_init(ADC_REF_AVCC, ADC_PRESCALE_8); Endless loop

while (true)
{
	// Reading the 4 times rounded values of the voltage of the 
	// thermistor
	value = adc_get_average_value(ADC_CHANNEL, 4);
	// Converting the values of ADC into celsius scale
	temperature = thermistor_calculate_celsius(value);
	// Converting the temperature in to text
	// To display the degree sign, the octal variable is 56
	sprintf(text, "%d\56C   ", temperature);
	// Displaying the text in the beginning of the third row of the LCD
	lcd_gfx_goto_char_xy(5, 3);
	lcd_gfx_write_string(text);
              hw_delay_ms(1000);
}
      return 0;

}

Photoresistor

Theory

Electrical symbol for a photoresistor
A photoresistor

A photoresistor is a sensor which electrical resistance is altered depending on the light intensity falling on it. The more intense is the light the more free carriers are formed and therefore the lower gets the resistance of the element. Two exterior metal contacts of the photoresistor are reaching through the ceramic base material to the light sensitive membrane, which determines the electrical resistance properties with its geometry and material properties. Since photo sensitive material itself has high resistance, with narrow, curvy track between the electrodes, low total resistance at average light intensity is gained. Similarly to the human eye, the photoresistor is sensitive at certain range of wavelengths and needs to be considered when selecting a photo element, otherwise it may not react to the light source used in the application. Following is simplified list of wavelengths of visible light segmented by colours:

Colour Range of wavelength (nm)
Purple 400 – 450
Blue 450 – 500
Green 500 – 570
Yellow 570 – 590
Orange 590 – 610
Red 610 – 700

A range of working temperature is set for photoresistor. Wishing the sensor to work at different temperatures, precising conversions must be executed, because the resisting properties of the sensors are depending on the temperature of the ambient.

For characterizing light intensiveness physical concept called light intensity (E) is used, this shows the quantity of light reaching any given surface. Measuring unit is lux (lx), where 1 lux represents, the even flow of light 1 lumen, falling on a surface of 1 m2. Hardly ever in reality falls light (living area) on a surface evenly and therefore light intensity is reached generally as a average number. Below are few examples of light intensity for comparison:

Environment Intensity of light (lx)
Full moon 0,1
Dusk 1
Auditorium 10
Class room 30
Sunset or sunrise 400
Operating room (hospital) 500 - 1000
Direct sun light 10000

Practice

The HomeLab is equipped with VT935G photoresistor. One pin of the photoresistor is connected to power supply and second pin to the analogue-digital converter (HomeLab II channel 1, HomeLab III channel 13). Between this pin and the ground resistor is also connected, which forms a voltage divider with the photoresistor. Since the electrical resistance of the photoresistor is decreasing as the light intensity falling on it grows, the measured voltage on the pin of the microcontroller grows as light intensity grows. It is worth to take into account that the photoresistor used in the HomeLab reacts most on orange and yellow light.

The sensor VT935G is not meant to be a specific measuring device. It is meant to be more a device to specify overall lighting conditions – is there a lighted lamp in the room or not. In this case one has to just measure the resistance of the sensor in the half dark room, note it in the program and compare measured values – is it lighter or darker.

The exercise here is a little bit more complex as the light intensity is measured also in lux. For doing this, exists an approximate formula and floating-point variables. In the C-language are floating-point variables float- and double-type variables, which can be used to present fractions. Their flaw is high demand of resources. Computers have special hardware to calculate floating-point variables, in the 8-bit AVR microcontroller calculations are executed in software which demands a lot of memory and time. If the flaws are not critical, the floating-point variables are worth using.

Relationship between resistance (R) of VT935G and intensity of light (E)

There is an approximate formula showing the relationship between the intensity of light and electrical resistance in the sensor datasheet. As seen on the graph (on the right), with using logarithm scale, the resistance and intensity of light are almost in linear relationship and form a in-line formula, because following conversion applies:

log(a/b) = log(a) - log(b)

The relation is characterised by the ascent of the factor γ (ascend of the line), which is 0,9 on VT935G sensor. We have also data on one of the points on that line: resistance 18.5 kΩ (RA) at 10 lx intensity of light (EA). Hence we have the coordinates of one point as well as the ascent of the line and for calculating any other point, we only need one coordinate. Meaning, if sensors' resistance (RB) is measured, it is possible to calculate from the equation of line, the intensity of light EB) that falls on the sensor. Finding EB from the equation of line:

log(EB) = log(RA/RB) / γ + log(EA)

EB = 10log(RA/RB) / γ + log(EA)

This gives the formula for calculating the intensity of light when the resistance is known. The resistance can not be measured directly with microcontroller. For this the photoresistor is in the voltage divider. The output voltage of this voltage divider is converted to a specific variable by the analogue-digital converter (ADC). To find the resistance, the output voltage (U2) of the voltage divider must be calculated first, using the ADC value, also comparison voltage (Uref) of the converter must be taken into account: The formula is following:

U2 = Uref * (ADC / 1024)

From the formula for voltage divider(check the chapter on voltage divider) the resistance of the upper photoresistor (R1) can be found:

R1 = (R2 * U1) / U2 - R2

In the following calculation of voltage and resistance, the known factors are replaced with numbers and indexes have been removed:

U = 5 * (ADC / 1024)

R = (10 * 5) / U - 10

For finding the intensity of light, simplifying conversions can be done:

E = 10log(18.5/R) / 0.9 + 1 = 10log(18.5/R) * 10/9 * 101 =

= 10log18.5*10/9 - logR*10/9 * 10 = (10log18.5*10/9 / 10logR*10/9) * 10 =

= (18.510/9 / R10/9) * 10 = 18.510/9 * 10 * R-10/9

By calculating the constant in front of the variable of the field R, the expression remains follows:

E = 255,84 * R-10/9

These formulas help only if the photoresistor on the module of the HomeLab is used. If circuit is used equipped with different components, respective variables need to be changed. Next, source code of the example program is presented, which measures and calculates using ADC and displays the intensity of light on the LCD.

In the example program variables of voltage, resistance and intensity are defined using type double of floating-point variables. The variables which should be used as floating-point variables must always contain a decimal point (it can be also just 0, because then the compiler understands it correctly).

HomeLab photoresistor demonstration LCD screen displays the approximate illuminance in lux #include #include #include #include #include

Main program int main(void) { char text[16]; unsigned short adc_value; double voltage, resistance, illuminance; Initializing the LCD

lcd_gfx_init();
      // Setting LCD backlight to work
      lcd_gfx_backlight(true);
// Clearing the LCD.
lcd_gfx_clear();
//Cursor on the position
lcd_gfx_goto_char_xy(3, 2);
// Name of the program
lcd_gfx_write_string("Luxmeter");
// Setting the ADC
adc_init(ADC_REF_AVCC, ADC_PRESCALE_8);
// Endless loop.
while (1)
{
	// Reading the average value of the photoresistor
	adc_value = adc_get_average_value(13, 10);
	// HomeLab II
	//adc_value = adc_get_average_value(1, 10);
	// Calculating the voltage in the input of the ADC
	// HomeLab II 		
	//voltage = 5.0 * ((double)adc_value / 1024.0);
	// HomeLab III
	voltage = 2.0625 * ((double)adc_value / 2048.0);
	// Calculating the resistance of the photoresistor 
              // in the voltage divider
	// HomeLab II
	//resistance = (10.0 * 5.0) / voltage - 10.0;
	// HomeLab III
	resistance = (33.0) / voltage - 10.0;
	
	// Calculating the intensity of light in lux		
	illuminance = 255.84 * pow(resistance, -10/9);
	// Dividing variable into two integer variable
	// to display it on the screen
	int8_t illu = illuminance;
  		int16_t illudp = trunc((illuminance - illu) * 1000);
	// Converting the intensity of light to text		
	sprintf(text, "%3u.%3u lux   ", illu,illudp); 
	// Displaying it on the LCD
	lcd_gfx_goto_char_xy(3, 3);
	lcd_gfx_write_string(text);
	// Delay 500 ms
	sw_delay_ms(500);
}

}

Microphone

Theory

Invalid Link
Microphone

Practice

Homelab microphone example Microphone sound level graph is shown on LCD and when sound level exceeds threshold an led lights up. #include #include #include #include #include

#define ADC_CHANNEL 12

Main program int main(void) { signed short mic; BYTE n; LCD setup function

lcd_gfx_init();

// ADC muunduri seadistamine
adc_init(ADC_REF_AVCC, ADC_PRESCALE_8);

// Set LED pin as output
pin_setup_output(led_yellow);
pin_set(led_yellow);	

// LCD background draw
FgColor = BLUE;
BkColor = YELLOW;	
lcd_gfx_fillScreen(YELLOW);
lcd_gfx_goto_char_xy(6,1);
lcd_gfx_write_string("Mikrofon");
lcd_gfx_drawLine(0,40,128,40,BLUE);	
FgColor = RED;
	
// Infinite loop
while (1)
{	
	// Clear graph area from LCD			
	lcd_gfx_fillRect(0, 41, 128, 119, WHITE); 		
	
	// Drawing the graph on LCD. Width of LCD is 128 pixels.		
	for (n = 0; n  30)
		{
			pin_toggle(led_yellow);
		} 
	}		
	
}

}

Infrared distance sensor

Theory

Sharp GP2Y0A21YK

For measuring the distance to an object there are optical sensors using triangulation measuring method. Company “Sharp” produces most common infra-red (IR) wavelength using distance sensors which have analogue voltage output. The sensors made by “Sharp” have IR LED equipped with lens, which emits narrow light beam. After reflecting from the object, the beam will be directed through the second lens on a position-sensible photo detector (PSD). The conductivity of this PSD depends on the position where the beam falls. The conductivity is converted to voltage and if the voltage is digitalized by using analogue-digital converter, the distance can be calculated. The route of beams reflecting from different distance is presented on the drawing next to the text

The route of the light beam from an IR distance sensor

The output of distance sensors by „Sharp“ is inversely proportional, this means that when the distance is growing the output is decreasing (decreasing is gradually slowing). Exact graph of the relation between distance and output is usually on the data-sheet of the sensor. All sensors have their specific measuring range where the measured results are creditable and this range depends on the type of the sensor. Maximum distance measured is restricted by two aspects: the amount of reflected light is decreasing and inability of the PSD registering the small changes of the location of the reflected ray. When measuring objects which are too far, the output remains approximately the same as it is when measuring the objects at the maximum distance. Minimum distance is restricted due to peculiarity of Sharp sensors, meaning the output starts to decrease (again) sharply as the distance is at certain point (depending on the model 4-20 cm). This means that to one value of the output corresponds two values of distance. This problem can be avoided by noticing that the object is not too close to the sensor.

Practice

Diagram of voltage-distance of IR distance sensor

The HomeLab set of sensors includes IR distance sensor SHARP GP2Y0A21YK. Measuring range of the sensor is 10 cm – 80 cm. The output voltage of this sensor is, depending on the distance measured, up to 3 V. The distance sensor can be connected to any ADC (the analogue-digital converter) channel of the HomeLab module. On the basis of previous exercises of sensors, it is easy to write a program which measures the output voltage of the distance sensors, but in addition, this exercise includes converting this output voltage to distance.

On the datasheet of the GP2Y0A21YK is graph of relation between its output voltage and measured distance. This graph is not a linear one, however the graph of inverse values of output voltage and distance almost is, and from that is quite easy to find the formula for converting voltage to distance. To find the formula, the points of the same graph must be inserted to any kind of spreadsheet application and then generate a new graph. In spreadsheet programs is possible to calculate automatically the trend-line. Next, the graph of GP2Y0A21YK corrected output voltage inverse value’s relation to the corrected inverse value of measured distance with linear trend-line is presented. To simplify, the output voltage is already converted to 10 bit +5 V values of analogue-digital converter with comparison voltage.

The graph of linearizing ADC value and distance

As seen on the graph, the trend-line (blue) overlaps quite precisely with the points of the graph. Such overlapping is achieved by using the help of the corrective constant. This corrective constant is discovered by using the trial-and-error method – many variables were tested until such was found which made the graph overlap the trend-line the most. This corrective constant of present graph is +2; this means that to all real distances +2 is added. This way the graph is very similar to the linear trend line and a generalization can be made and say that the relation between the distance and the voltage is following:

1 / (d + k) = a * ADC + b

where

  • d - distance in centimeters.
  • k - corrective constant (fund using tial-and-error method)
  • ADC - digitalized value of voltage.
  • a - linear member (value is determined by the trend line equation)
  • b - free member(value is determined by the trend line equation)

Distance d can be expressed from the formula:

d = (1 / (a * ADC + B)) - k

Now it is basically possible to calculate the distance by using this formula, but this requires floating-point calculations, since while dividing fractions will occur. Because the microcontroller operates using integers, the formula must be simplified and converted to larger ratios. Then when dividing the quotient with a linear-member it will look as follows:

d = (1 / a) / (ADC + B / a) - k

When introducing the corrective constant to the formula and also the linear-member and the free-member from the trend-line equation, the formula for calculating the distance will be:

d = 5461 / (ADC - 17) - 2

This formula is computable with 16-bit integers and completely suitable to AVR. Before calculating, must be ensured that the value of the ADC is over 17, otherwise dividing with 0 or negative distance may occur.

Following is the function for converting the values of ADC to centimeters, it is written in the library of the HomeLab. Linear- and free-member and corrective constant are not stiffly written into the function, they are fed with the structure object parameters of the IR distance sensor. By holding the parameters in separate constant, it is easy to add new IR distance sensors to the program.

The structure of the parameters of the IR distance sensors typedef const struct { const signed short a; const signed short b; const signed short k; } ir_distance_sensor; The object of the parameters of GP2Y0A21YK sensor const ir_distance_sensor GP2Y0A21YK = { 5461, -17, 2 };

Converting the values of the IR distance sensor to centimeters Returns -1, if the conversion did not succeed signed short ir_distance_calculate_cm(ir_distance_sensor sensor,

unsigned short adc_value)

{

if (adc_value + sensor.b = 0)
	{			
		// Conversing distance to text
		sprintf(text, "%3d cm   ", distance);
	}
	else
	{		
		// Creating the text for unknown distance
		sprintf(text, "Error   ");
	}
	
	lcd_gfx_goto_char_xy(1,3);
	lcd_gfx_write_string(text);
	sw_delay_ms(500);
}

}

Ultrasonic distance sensor

Theory

Ultrasonic distance sensor SRF05

Ultrasonic distance sensor determines the distance to an object by measuring the time taken by the sound to reflect back from that object. The frequency of the sound is somewhere in the range of ultrasound, this ensures more concentrated direction of the sound wave because sound at higher frequency dissipates less in the environment. A typical ultrasonic distance sensor consists of two membranes. One membrane produces sound, another catches reflected echo. Basically they are speaker and microphone. The sound generator generates short (the length is a couple of periods) ultrasonic impulses and triggers the timer. Second membrane registers the arrival of the sound impulse and stops the timer.From the timers time it is possible to to calculate the distance traveled by the sound. The distance to the object is half of the distance traveled by the sound wave.

Working principle of the ultrasonic distance sensor.

The ultrasonic sensors have quite a lot of use in everyday life. They are used to replace measuring tapes in measuring devices at construction sites. Cars are equipped with ultrasonic parking sensors. Besides measuring distances, they can just register the presence of the object in the measuring range, for example in danger zones of working machines. If ultrasound transmitter and receiver are separated, the flowing speed of the substance between them can be measured, because the sound wave travels slower upstream and vice versa.

Practice

HomeLab is equipped with Devantech SRF04/SRF05 ultrasonic distance sensor. SRF04/SRF05 is just a sensor and it does not give direct information about the distance. Besides the power supply pins the sensor has also a triggering pin and a echo pin. One important difference between the sensor SRF04 and SRF05 is that it is possible in case of SRF05 use a single physical connector pins for the trigger and the echo signal. This allows the sensor to use the standard three-wire connector (power, ground and signal). When the triggering pin is set high the sensor generates 40 kHz ultrasonic wave which is 8 periods long. At that moment the echo pin becomes high and remains high until the reflected sound is reached back to the sensor. So the echo signal reflects basically the time during which the sound reaches to the object and comes back from the object. By measuring that time and multiplying it by the speed of sound and then divide it by two, is calculated the distance to the object.

To use the SRF04/SRF05 with the AVR, its trigger pin and echo pin should be connected to some of the AVR pins. For measuring time, it is suitable to use a 16-bit timer, for example timer3. Following is a function which is based on the Atmega2561 controller and executes all measuring procedures – it generates the signal of the trigger, starts the timer, measures the length of the echo signal and converts it to the distance in centimeters. The function is blocking, meaning the processor is occupied by it until the result of measuring is received or the measuring takes too long time. The faster the echo arrives the faster the result is returned. If the echo does not arrive, the function waits for it for 36 ms and returns to 0. It is important to leave approximately 20 ms break between each measuring, to able the sound generated during the previous measuring to die out and the new measuring will not be affected. It is important to notice that the sound waves don’t disturb each other, when several ultrasonic sensors are used simultaneously

#define ULTRASONIC_SPEED_OF_SOUND 33000 cm/s Ultrasonic distance measuring unsigned short ultrasonic_measure_srf05(pin triggerecho) {

  // Pin setup
  pin_setup_output(triggerecho);
  // Set timer 3 to normal mode
  // with period of F_CPU / 8
  timer3_init_normal(TIMER3_PRESCALE_8);      
  // Create trigger pulse
  pin_set(triggerecho);
  
  // Reset timer
  timer3_overflow_flag_clear();
  timer3_set_value(0);    
  
  // Wait ~10 us
  while (timer3_get_value() < 18) {}
  
  // End trigger pulse
  pin_clear(triggerecho);
  
  //short delay
  sw_delay_ms(1);
  
  //set the pin as input
  pin_setup_input_with_pullup(triggerecho);
  
  // Wait for echo start
  while (!pin_get_value(triggerecho))
  {
      // Timeout ?
      if (timer3_overflow_flag_is_set())
      {
          return 0;
      }
  }
  
  // Reset timer again
  timer3_set_value(0);
  
  // Wait for echo end    
  while (pin_get_value(triggerecho))
  {
      // Timeout ?
      if (timer3_overflow_flag_is_set())
      {
          return 0;
      }
  }
  
  // Convert time to distance:
  //   distance = timer * (1 / (F_CPU / 8)) * speed / 2
  return (unsigned long)timer3_get_value() *
      ULTRASONIC_SPEED_OF_SOUND / (F_CPU / 4);

}

Presented function allows the user to choose the echo/trigger pin, so the sensor can be connected where it is more suitable or where is more space. In addition, the freedom of choosing the pins allows to use the function also elsewhere than only in the HomeLab. Presented function belongs already to the library of the HomeLab so it is not necessary to write it. One thing must be remembered: the function in the library of the HomeLab is stiffly connected to the clock rate of the Controller module of the HomeLab. Using the function with other clock-rates, it would give incorrect result. To use the function with other clock-rates, it should be written in the program manually. Following code of program demonstrates the use of SRF04/SRF05 ultrasonic sensor with the library of the HomeLab. When connecting the sensor it is very important to observe the power polarity. Incorrectly connected sensor becomes broken.

The example program of the ultrasonic distance sensor of the HomeLab Measuring the distance is blocking. #include #include #include #include #include

Pins of ultrasonic sensor Robotic HomeLab II pin pin_pin_trigger_echo = PIN(F, 2); Robotic HomeLab III pin pin_trigger_echo = PIN(B, 2);

Main program int main(void) { unsigned short distance; char text[16]; Robotic HomeLab II

// Switching to external sensors
/*
pin ex_sensors = PIN(G, 0);
pin_setup_output(ex_sensors);
pin_set(ex_sensors);

*/

// Initialization of LCD
lcd_gfx_init();

Clearing the LCD lcd_gfx_clear(); Line selection

lcd_gfx_goto_char_xy(1,1);

Name of the program lcd_gfx_write_string(„Ultrasonic sensor“); Little delay

sw_delay_ms(100);

Endless loop. while (1) { Measuring

	distance = ultrasonic_measure_srf05(pin_trigger_echo);
	// Was the measuring successful ?
	if (distance > 0)
	{			
		// converting the distance to text.
		sprintf(text, "%3d cm   ", distance);
	}
	// Were there errors during the measuring ?
	else
	{
		// Text of the error.
		sprintf(text, "Error    ");
	}			
	// Displaying the text on the LCD
	lcd_gfx_goto_char_xy(3, 3);
	lcd_gfx_write_string(text);

Little delay sw_delay_ms(500); } } To make sure that the ultrasonic sensor actually start working, you should check whether the small LED will flash every measurement which is located on the back of the sensor.

 
==== Passive infrared sensor (PIR) ==== Necessary knowledge: [HW] User Interface Module, [HW] Combo module,
[AVR] Digital Inputs/Outputs, [LIB] Pins === Theory === [PIR sensor] Passive infrared sensor measures infrared (IR) radiation from objects in it's field of view. All objects emit some low level radiation. The hotter something is the more radiation is emitted. Human eye is not capable to see IR radiation, but it's possible to use special cameras and sensors to detect it. The sensor is called passive because it doesn't emit light to get measurements. The sensor in PIR is actually split into two parts. The reason for that is to measure motion. Two parts of sensor are wired up in a way that they cancel each other out. If one detects more or less IR radiation than the other, the output will swing high or low. PIR sensor is mostly used for detecting living being movement and thus is generally known as passive infrared detector (PID). The sensor is also sensitive enough to even detect IR radiation source movement while the object is already in it's field of view. PID usually consists from three components: * passive infrared sensor (PIR) * lens for directing radiation to the sensor * control circuit [PID - motion detector] === Practice === PID sensors output is usually simple digital signal. If the sensor has detected something then it usually outputs high impulse which stays high for a given time period (the time might be adjustable). This gives the sensor capability to switch a relay or be used as an input for microcontroller. These devices can turn on a light or be used as a part of alarm system. Using the detector with a microcontroller is not much different from reading a regular push button switch. PID can be connected to digital or analog input. Be sure to check the pinout of the detector before connecting it to microcontroller. It is especially important to not mix up power and ground pins cause failure to do so usually ends up in breaking the detector. On Robotic HomeLab III the detector has to be connected to Combo module encoder input if the sensor requires 5V power or analog/digital input of choice if voltage requirement is 3.3V. Be sure to check the sensor voltage rating before connecting. If the 5V encoder input is used then the external power source has to be connected on the Controller module.
 
Robotic HomeLab PID sensor (detector) example program #include

Detector input pin define Homelab II pin pir_pin = PIN(F, 0); Homelab III pin pir_pin = PIN(C, 4);

Main program int main(void) { Setting LED pins to output

pin_setup_output(led_green);
pin_setup_output(led_red);
// Setting detector pin as input
pin_setup_input(pir_pin);

Endless loop while (1) { If the sensor has not detected anything then the green LED is on

  // If something is detected then the RED led turns on
  if(pin_get_value(pir_pin) == 0)
  {
      led_on(led_green);
led_off(led_red);
}
  else
  {
led_on(led_red);
led_off(led_green);
  }
}

}

Encoder

Accelerometer

Teooria

Kiirendusandur

Kiirendusandurit kasutatakse peamiselt kiiruste muutuste mõõtmiseks. Samuti saab kiirendusanduriga mõõta anduri nurka maapinna suhtes. Kiirendusandurid on konstrueeritud ja valmistatud mikroelektromehaanika tehnoloogial (inglise keeles Microelectromechanical system, lühend MEMS), kus elektroonika ja mehaanika komponendid on integreeritud mikrotasandil.

Tüüpiline kiirendusandur koosneb mikrofreesitud mahtuvuslikust andurelemendist (g-rakk) ja mõõte- ning andmetöötluselektroonikast. Mõõteelement koos elektroonikaga on suletud vee ja õhukindlalt anduri korpusesse. G-rakk on mikrokiipi söövitatud polüsilikooni kiht, mis koos kahe fikseeritud mahtuvusliku plaadiga moodustab kaks kondensaatorit. Kui andurile rakendada mingi kiirendus, siis g-raku keskmine kiht liigub vastavalt ühe või teise fikseeritud plaadi poole ning kondensaatorite mahtuvus muutub proportsionaalselt kiirendusele. Andurisse sisse ehitatud elektroonika tegeleb g-rakkude mõõtmisega ning analüüsimisega. Elementidest tulev informatsioon võimendatakse, filtreeritakse ning teisendatakse pingeks, mida saab otse ühendada mikrokontrolleri sisendiga. Tavaliselt lisatakse anduritesse ka 0G väljund, millega on võimalik kontrollerisse tekitada katkestus juhul kui andur tuvastab 0G ehk kukkumise.

Praktika

Kodulabori lisakomplektiga on kaasas lihtne 3-teljeline MMA7361L kiibil põhinev kiirendusandur. Kiirendusandur võimaldab valida kahe erineva mõõtepiirkonna vahel, milleks on ±1.5g ja ±6g. Anduril on sisseehitatud temperatuuri kompensatsioon, madalpääsu filter, testfunktsioon ja madala voolutarbega puhkeoleku režiim.

Kiirendusanduri viigud
Tähis plaadil Signaali tüüp Kirjeldus
0GD Digitaalväljund 0G tuvastamise
signaal
X Analoogväljund X-telje väljundsignaal
Y Analoogväljund Y-telje väljundsignaal
Z Analoogväljund Z-telje väljundsignaal
G Toide Maa
+ Toide Toide 3.0-3.6 V
G Toide Maa
SLEEP Digitaalsisend Puhkerežiim,
madal olek: aktiivne
GS Digitaalsisend Režiimi valik
ST Digitaalsisend Enesetesti funktsioon

Kiirendusanduri lugemiseks on vaja kasutada kontrolleril kolme ADC sisendit (1 iga telje jaoks). Teiste anduri funktsioonide jaoks saab kasutada digitaalsignaale. Näitekood näitab kanalitest mõõdetud ADC väärtust ning joonistab kiirendusanduri lugemid ka punktidena LCD-le.

Kodulabori kiirendusanduri näidisprogramm Loetakse kiirendusanduri kolme telje väärtused ja kuvatakse need ekraanil X ja Y telje näidud visualiseeritakse tingliku punktina ekraanil #include #include #include Väärtuste teisendusfunktsioon long map(long x, long in_min, long in_max, long out_min, long out_max) {

return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;

}

Põhiprogramm int main(void) { LCD ekraani algseadistamine

lcd_gfx_init();
lcd_gfx_write_string("Kiirendusandur");
// ADC muunduri algseadistamine
adc_init(ADC_REF_AVCC,ADC_PRESCALE_128);
// Lõputu tsükkel
while (1)
{
	char buffer[60];
	// x, y, z telgede analoogväärtuse lugemine
	uint16_t x = adc_get_value(1);
	uint16_t y = adc_get_value(2);
	uint16_t z = adc_get_value(3);
	// Kiirendusanduri telgede lugemite teisendamine ekraani
	// mõõtkavasse, et neid saaks punktidena ekraanil kuvada
	uint16_t x_map = map(x,950,1300,128,0);
	uint16_t y_map = map(y,1000,1400,0,160);
	// Lugemite teisendamine tekstiks ja LCD ekraanile kuvamine
	sprintf(buffer,"x: %4d\ny: %4d\nz: %4d\n",x,y,z);
	lcd_gfx_goto_char_xy(0,2);
	lcd_gfx_write_string(buffer);
	// Punktide joonistamine
	lcd_gfx_drawPixel(x_map, y_map);
	sw_delay_ms(10);
}

}

 

Combined humidity-temperature sensor

Teooria

DHT11

Temperatuuri ja niiskuse mõõtmiseks on olemas väga lai valik andureid, millest osa on ka kombineeritud andurid, mis väljastavad nii temperatuuri, kui ka niiskuse. Hinna poolest väga soodsad andurid on DHTxx seeria andurid, mille täpsus pole küll väga suur, kuid täiesti piisav tavakasutajale. Temperatuuriandureid toodetakse erineval tehnoloogial, millest termistoridest oli juttu ka eelmises peatükis. Lisaks termistor tüüpi temperatuurianduritele on olemas veel termopaarid, kiirguse kaudu temperatuuri mõõtvad andurid, metalltakistuse kaudu temperatuuri mõõtvad andurid, jne. Sõltumata anduri füüsikalisest mõõteprintsiibist on mitmetele anduritele ühte korpusesse koostatud ka juhtelektroonika, mis väljastab anduri lugemi digitaalse signaalina. Nagu eelpool mainitud on olemas kombineeritud andurid, mis lisaks temperatuurile mõõdavad veel mingit muud keskkonna parameetrit, millest kõige tüüpilisem on suhtelise niiskuse mõõtmine.

Niiskus on sisuliselt vee osakaal õhus. Niiskuse erinev väärtus mõjutab seadmete tööd, korrosiooni ja elusorganismide talitlusvõimet ning elukeskkonda olulisel määral ja seetõttu on robottehnilistes seadmete oluline mõõta suhtelise niiskuse osakaalu õhus, et vastavalt sellele mingeid protsesse juhtida. Levinud niiskusanduri kasutusvaldkond on targa maja või targa kasvuhoone rakendused, kus vastavalt õhuniiskuse tasemele lülitatakse sisse konditsioneere, ventilaatoreid või niisutussüsteeme. Niiskusandurid toimivad jämedalt võttes kahel printsiibil, kus mõõtesuuruse elektriline teisendus toimub vastavalt mahtuvuse või takistuse kaudu. Mõlemal juhul teisendatakse õhu suhteline niiskus elektriliseks signaaliks, mis on sõltuvalt andurist, kas lihtne analoogsignaal (mingi pingevahemik) või mõne andmevahetusprotokolli digitaalsignaal. Levinud digitaalsignaali tüübid niiskuse ja temperatuuri anduritel on nn 1-juhtme (inglise keeles 1-wire) signaal, kus andmevahetus toimub 1 füüsilise viigu kaudu. 1-juhtme andmevahetusprotokolli töötas välja Dallas Semiconductor lihtsamate seadmete ja anduritega suhtlemiseks. Lisaks mõlemasuunalisele andmevahetusele on võimalik ka seadme toide sama juhtme külge ühendada. Liides võimaldab ühele siinile ühendada üle 75 seadme, moodustades mikrokohtvõrke (inglise keeles MicroLan). MicroLan võrgus on üks juhtseade, mis juhib võrgus liiklust ja tagab, et siinil olevad seadmed ei üritaks korraga rääkida.

1-juhtme tüüpi andurite võrguühendused

1-juhtme ühendus on peamiselt kasutusel erinevate andurite ja mäludega suhtlemiseks. Saavutatav maksimaalne kiirus jääb 16,3 kbit/s piirimaile. Juhtseade alustab suhtlust taaskäivituse (inglise keeles reset) pulsiga, mis tõmbab siini maha vähemalt 480 µs. Peale seda järgneb 8 bitine korraldus, mida kuulavad kõik seadmed. Seade, millele see adresseeritud on, vastab. Andmeid saadetakse ja võetakse vastu 8 bitilistes gruppides, kus igal seadmel on unikaalne 64 bitine seerianumber. Bittide edastamine toimub pulsi pikkuse järgi. „1“ saatmiseks tekitatakse pulss pikkusega 1 - 15 µs ja „0“ saatmiseks 60 µs.

Praktika

Näiteks on toodud kaks erinevat temperatuuri/niiskuse andurit, mis kasutavad 1-juhtme andmevahetusliidest.

1-juhtme standardset andmevahetusliidest kasutab digitaalne termomeeter DS18S20, mille mõõdetav temperatuurivahemik on -55…+100 °C. DS18S20 temperatuurianduri saab ühendada tavalisse digitaalviiku, kus ühele siinile võib ühendada mitu andurit. Samuti tuleb valida anduri toiteviis, mis võib olla eraldi toiteviik või kasutatakse sama viiku, kuhu on ühendatud andmesidekanal. Andmesidekanaliga kokkuühendatud ühendusviisi kutsutakse parasiittoiteks ja sellisel juhul on kasutuses ainult kaks juhet.

Robootika Kodulaboris on standardse 1-juhtme andmeside liidese kasutamiseks loodud eraldi teek onewire.h, mis sisaldab 1-juhtme siini juhtkäskusid. Andurispetsiifiline teek on ds18x20.h. DHTxx seeria andurite funktsionaalsus on integreeritud üldisesse andurite teeki sensors.h.

Lisaks standard 1-juhtme protokollile on sarnastel omadustel põhinevad, kuid veidi erinevat toimeloogikat kasutatavad 1-juhtme siini andmevahetusprotokollid. Ühte sellist rakendatakse ka odavate kombineeritud niiskuse temperatuuriandurite DHTxx seeria juures. DHTxx andmesidepakett jaguneb järgmiselt:

  • Start bitt
  • niiskuse kõrgem bait
  • niiskuse madalam bait
  • temperatuuri kõrgem bait
  • temperatuuri madalam bait
  • CRC kontrollbait (eelnevate baitide summa madalaim bait)

DHT11 anduril on temperatuuri ja niiskuse mõõtetulemus otseselt loetav kõrgemast baidist ning madalam bait on tühi. DHT22 anduril on temperatuuri ja niiskuse mõõtetulemus paketis 16 bitise arvuna ning ühe komakohaga, st tagastatud number 245 vastab temperatuurile 24,5 °C.

DHTxx ühendamise skeem

Andmesiinil käib suhtlus avatud kollektor režiimis. See tähendab, et kõrge nivoo tuleneb siinile ühendatud pullup takistist ning andur ning mikrokontroller tekitavad andmebitte siini kordamööda madalale tõmmates. Start bitiks loetakse olukorda, kus kontroller tõmbab siini madalaks vähemalt 18 ms, ning pärast seda laseb kõrgeks tagasi. Pärast start biti saadab andur siinile vastuse biti ning mõõdetud tulemused. Andmete 0 ja 1 bitt on defineeritud biti kõrge osa laiusega. Bitt 0 on defineeritud kui 50 µs madal pulss, millele järgneb 26-28 µs kõrge pulss. Bitt 1 on defineeritud kui 50 µs madal pulss, millele järgneb 70 µs kõrge pulss. Andmepakett lõppeb 50 µs pikkuse madala pulsiga ning lõpuks laseb andur siini tagasi kõrgeks. Tarkvaraline realisatsioon on leitav teegi failist sensors.c funktsiooni DHT_update alt.

Anduri lugemine on realiseeritud Kodulabori andurite teegis sensors.h. Käsuga DHT_update() uuendatakse kaht globaalset muutujat dht_temp (temperatuur) ja dht_hum (niiskus).

Näitekoodis loetakse PORTE viiku 0 ühendatud andurit DHT11 ja PORTE viiku 1 ühendatud andurit DHT22.

DHTxx andmebitid

Kodulabori DHT niiskus ja temperatuurianduri lugemise näidisprogramm LCD-le kuvatakse temperatuur ja niiskus ning temperatuuri muutuse graafik #include #include #include #include #include

Andurite signaali ühendusviigu defineerimine pin DHTpin = PIN(E,0); Põhiprogramm int main(void) {

  char text[60];
  char i=0;
  // LCD ekraani algseadistamine
  lcd_gfx_init();
  // Lõputu tsükkel
  while (1)
  {
      lcd_gfx_goto_char_xy(3, 0);
      lcd_gfx_write_string("DHTxx andur");
      
      // DHTxx anduri näidu lugemine ja kuvamine LCD-l
      // DHT_update esimene parameeter on anduri tüüp (DHT11 või DHT22)
      DHT_update(DHT22,DHTpin);
      lcd_gfx_goto_char_xy(0,8);
      sprintf(text," Temperature: %2dC\n Humidity: %2d%%",dht_temp/10,dht_hum/10);
      lcd_gfx_write_string(text);
      // Temperatuuri graafiku joonistamine (toimib vaid kodulabor III generatsioonil)
      lcd_gfx_drawPixel(i++,100-(dht_temp/10));
      sw_delay_ms(500);
      // Graafiku otsast alustamine, kui joon on lõppu jõudnud
      if (i>126)
      {
          i=0;
          lcd_gfx_clear();
      }
  }

}

Force sensor

Theory

Force-sensing resistor
Force-sensing resistor layers

FSR (force-sensing resistor) sensor allow you to detect physical pressure, squeezing and weight. FSR is basically a resistor that changes its resistive value (in ohms Ω) depending on how much it’s pressed. These sensors are fairly low cost and easy to use but they're rarely accurate. They also vary some from sensor to sensor perhaps 10%. It means when you use FSR's you should only expect to get ranges of response. As with all resistive based sensors force-sensing resistors require a relatively simple interface and can operate satisfactorily in moderately hostile environments. Compared to other force sensors, the advantages of FSR are their size and good shock resistance. However FSR will be damaged if pressure is applied for a longer time period (hours).

FSR consists of a conductive polymer, which changes resistance in a predictable manner following application of force to its surface. They are normally supplied as a polymer sheet or ink that can be applied by screen printing. The sensing film consists of both electrically conducting and non-conducting particles suspended in matrix. The particles are sub-micrometre sizes, and are formulated to reduce the temperature dependence, improve mechanical properties and increase surface durability. Applying a force to the surface of a sensing film causes particles to touch the conducting electrodes changing the resistance of the film.

Force-sensing resistors are commonly used to create pressure-sensing „buttons“ and have applications in many fields, including musical instruments, car occupancy sensors, and robotics.

Practice

Force conductance graph
Voltage divider schematics for the sensor

Pololu FSR with 12.7 mm diameter circular active area are exhibits a decrease in resistance with an increase in the force applied to the active surface. Its force sensitivity is optimized for use in human touch control of electronic devices. The force vs. resistance characteristic provides an overview of FSR typical response behavior. For interpretational convenience the force vs. resistance data is plotted on a log/log format. In general, FSR response approximately follows an inverse power-law characteristic (roughly 1/R).

The easiest way to measure a resistance of FSR is to connect one terminal to power and the other to a pull-down resistor to ground. Then the point between the fixed pull-down resistor and the variable FSR resistor is connected to the analogue input of a Controller board. In this configuration the analogue voltage reading ranges from 0V (ground) to about 5V (or about the same as the power supply voltage). As the resistance of the FSR decreases the total resistance of the FSR and the pull-down resistor decreases from about 100Kohm to 10Kohm. That means the current flowing through both resistors increases which in turn causes the voltage across the fixed 10K resistor to increase.

Measuring the Newton force by the FSR it is good idea to map analogue voltage reading ranges to 0 V to supply voltage. After that you can calculate the FSR resistance using following formula:

RFSR = ( (Vcc - U) * R1) / U

Where: RFSR - FSR Resistance Vcc – supply voltage. Usually 5 V U – The measured voltage. The ADC reading must be converted to 0 V - Vcc R1 – resistor. 10 k

Then you can calculate the conductivity CFSR in S/m [Siemens per meter]. The conductance is plotted vs. force (the inverse of resistance: 1/r). This format allows interpretation on a linear scale.

CFSR = 1 / RFSR

Use the FSR guide graphs on the datasheet to approximate the force. It depends on the measurable range. For example (0-1 Kg) low force range can be use formula:

FFSR = CFSR / 80

The example program of the force sensor shows the measured force (Newtons) and weight (kg) on the LCD.

 

#include #include #include #include #include

Map a value from one range to another. long map(long x, long in_min, long in_max, long out_min, long out_max) { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } Main program int main(void) {

signed short value; // The analog reading.
char text[16];
int voltage; // The analog reading converted to voltage.
unsigned long resistance; // The voltage converted to resistance.
unsigned long conductance; 
long force; // The resistance converted to force. 
long weight; // The force converted to weight. 

Set the external sensors pins. pin ex_sensors = PIN(G, 0); pin_setup_output(ex_sensors); pin_set(ex_sensors); LCD initialization.

lcd_gfx_init();

Display clearing. lcd_gfx_clear(); Move the cursor to the right of the screen.

lcd_gfx_goto_char_xy(1,1);

Print the name of the program. lcd_gfx_write_string(„Force sensor“); Set the ADC.

adc_init(ADC_REF_AVCC, ADC_PRESCALE_8);

An endless loop. while (true) { Converting and averaging channel 0 value.

	value = adc_get_average_value(0, 4);
	// Analog voltage reading ranges from about 0 to 1023 
	// which maps to 0V to 5V   (= 5000mV)
        voltage = map(value, 0, 1023, 0, 5000);
	// The voltage = Vcc * R / (R + FSR) where R = 10K and Vcc = 5V
	// so FSR = ( (Vcc - V) * R) / V
	// fsrVoltage is in millivolts so 5V = 5000mV
	resistance = 5000 - voltage;     
        resistance *= 10000; // 10K resistor
        resistance /= voltage; // FSR resistance in ohms.

conductance = 1000000; We measure in micromhos. conductance /= resistance; Conductance in microMhos.

Move the cursor to the right of the screen. lcd_gfx_goto_char_xy(1,3); Calculate the force.

              force = conductance / 80;
              sprintf(text, "%lu Newtons   ", force);
	 
	// Printing of the force.
	lcd_gfx_goto_char_xy(1,3);
	lcd_gfx_write_string(text);
	// Printing and calculating of the weight.
	lcd_gfx_goto_char_xy(1,4);
	weight = force / 9,8;
	sprintf(text, "%lu kg   ", weight);
	lcd_gfx_write_string(text);

Delay. sw_delay_ms(500); } } ==== Lidar ==== Necessary knowledge: [HW] Communication Module, [HW] User Interface Module, [LIB] Serial Interface, [LIB] Graphic LCD, [LIB] Sensors === Theory === [SICK Laser Rangefinder (LIDAR)] LIDAR (Light Detection and Ranging) is an optical remote sensing system which can measure the distance of a target by illuminating it with light. LIDAR technology is being used in Robotics for the perception of the environment as well as object classification. The ability of LIDAR technology to provide 2D elevation maps of the terrain, high precision distance to the ground, and approach velocity can enable safe landing of robotic and manned vehicles with a high degree of precision. Lidar consists of a transmitter which illuminates a target with a laser beam, and a receiver capable of detecting the component of light which is essentially coaxial with the transmitted beam. Receiver sensors calculate a distance, based on the time needed for the light to reach the target and return. A mechanical mechanism with a mirror sweeps the light beam to cover the required scene in a plane or even in three dimensions, using a rotating nodding mirror. One way to measure the time of flight for the light beam is to use a pulsed laser and then measure the elapsed time directly. Electronics capable of resolving picoseconds are required in such devices and they are therefore very expensive. Another method is to measure the phase shift of the reflected light. [Working principle] Collimated infrared laser is used to the phase-shift measurement. For surfaces, having a roughness greater than the wavelength of the incident light, diffuse reflection will occur. The component of the infrared light will return almost parallel to the transmitted beam for objects. [Phase-shift measurement] The sensor measures the phase shift between the transmitted and reflected signals. The picture shows how this technique can be used to measure distance. The wavelength of the modulating signal obeys the equation: c = f ∙ τ where c is the speed of light and f the modulating frequency and τ the known modulating wavelength. The total distance D' covered by the emitted light is: D' = B + 2A = B + (θ * τ) / 2π where A is the measured distance. B is the distance from the phase measurement unit. The required distance D, between the beam splitter and the target, is therefore given by D = τ * θ / 4π where θ is the electronically measured phase difference between the transmitted and reflected light beams. It can be shown that the range is inversely proportional to the square of the received signal amplitude, directly affecting the sensor’s accuracy. === Practice === [Map created by Lidar] In autonomous robotics as well as industrial robotics SICK laser rangers are very widely used. The SICK LMS 200 can easily be interfaced through RS-232 or RS-422, providing distance measurements over a 180 degree area up to 80 meters away. This lidar is based on a time-of-flight measurement principle. The example output of one scan measurement result is shown in the picture on the right. [Connection diagram] To make the SICK operational, it must be wired for power and communication. On the back of the SICK there are two connectors that looks like serial port connectors. The connector with the female end is for power and the connector with the male end is for communications. The power and the serial cable should be wired as shown in the picture. Lidar can be connected with Robotic HomeLab Communication module using one of the RS-232 connectors. Power must be taken from external power source and this is not included in Robotic HomLab kit. Required dc power voltage is 24 V. The SICK receives commands as streams of bytes through the serial port. When transmitting data, it sends back streams of bytes corresponding to distance measurements at a given angle. To grab data from the SICK, you must first send a start string to tell the sensor to start sending data. This string is: Hexadecimal Form: 02 00 02 00 20 24 34 08 Decimal Form: 2 0 2 0 32 36 52 8 If the start string is successfully sent, Lidar will begin streaming data over RS232. Incoming data from a scan is sent sequentially as the sensor scans through 180°. For example if the sensor is set to scan 180° with resolution of 0.5° the first data point which was sent will correspond to 0°, the next will correspond to 0.5°, the following to 1°, and so on. This means there is total of 361 data points. Each distance measurement is sent in the form of two bytes. The least signifficant byte is sent first followed by the most signifficant byte. Operating in metric mode the unit for the measurements is in milimeters. Finally to stop the sensor from sending data a stop string must be sent. This string is: Hexadecimal Form: 02 00 02 00 20 25 35 08 Decimal Form: 2 0 2 0 32 37 53 8 Following example shows how to initiate Lidar and get the count of package. #include #include #include #include #include Defining USART interface. usart port = USART(0);

Defining button pins. pin button1 = PIN(C, 0); pin button2 = PIN(C, 1); Initialize static inline void init() {

// Setting buttons pins as inputs.
pin_setup_input_with_pullup(button1);
pin_setup_input_with_pullup(button2);

// Set-up of the LCD.
lcd_gfx_init();

Cleaning the screen. lcd_gfx_clear(); Switching on the background light.

lcd_gfx_backlight(true);	

Displaying the name of the program. lcd_gfx_goto_char_xy(3, 1); lcd_gfx_write_string(„Lidar“); The set-up of the USART interface.

usart_init_async
(
	port,
	USART_DATABITS_8,
	USART_STOPBITS_ONE,
	USART_PARITY_NONE,
	USART_BAUDRATE_ASYNC(9600)
);		

}

Main program int main(void) { unsigned char new_value1, new_value2, old_value1 = 0, old_value2 = 0; char c; int i = 0; int count = 0; char text[16]; Initialize

init();	
// Endless cycle
while (1)
{	 
	// Reads buttons states
	new_value1 = pin_get_debounced_value(button1);
	new_value2 = pin_get_debounced_value(button2);
	 
	// Button S1 is pressed.
	if((!new_value1) && (old_value1))
	{	
		//Send "02 00 02 00 20 24 34 08" to start scanning.
				
		usart_send_char(port, 0x02);
		usart_send_char(port, 0x00);
		usart_send_char(port, 0x02);
		usart_send_char(port, 0x00);
		usart_send_char(port, 0x20);
		usart_send_char(port, 0x24);
		usart_send_char(port, 0x34);
		usart_send_char(port, 0x08);
	}
	// Button S2 is pressed.
	if((!new_value2) && (old_value2))
	{
		//Send "0x 02 00 02 00	20 25 35 08" to stop scanning.
		usart_send_char(port, 0x02);
		usart_send_char(port, 0x00);
		usart_send_char(port, 0x02);
		usart_send_char(port, 0x00);
		usart_send_char(port, 0x20);
		usart_send_char(port, 0x25);
		usart_send_char(port, 0x35);
		usart_send_char(port, 0x08);				
	}
	 
	// Remembers the last keys values.
	old_value1 = new_value1;
	old_value2 = new_value2;
	
	// Try to read serial port
	if (usart_try_read_char(port, &c))
	{
		// Find a header "0x 02 81 D6 02 B0 69 41"
		// Very basic package start search.	
		if(c == 0x02) i++;
		if(c == 0x81) i++;			
		if(c == 0xD6) i++;			
		if(c == 0x02) i++;			
		if(c == 0xB0) i++;			
		if(c == 0x69) i++;			
		if(c == 0x41) i++;
		
		//If there is an header
		if(i >= 7)
		{
			//Increse packet counter
			count++;
			//Displaying packet count on the LCD.
			lcd_gfx_goto_char_xy(0, 3);
			sprintf(text, "Pakette: %i", count);
			lcd_gfx_write_string(text);
			i=0;
		}
	}					
}

}

1-wire temperature sensor

Theory

Temperature sensor

Dallas Semiconductor Corp. worked out a communication bus system for simple sensors and other equipments called 1-wire protocol. This protocol provides low-speed data exchange, signaling and power over single signal wire. It is possible to connect up to 75 devices to one bus, forming MicroLan networks. MicroLan networks have one master unit, what controls network's traffic and ensures that one device at a time uses the bus. 1-wire protocol is similar to I2C protocol, but has lower data rates, longer distance range and only one wire for all communication.

1-wire communication is mostly used for communicating between different sensors and memory units. Bus data transfer rate is approximately 16.3 kbit/s. Communication is started by a master with the „reset“ pulse, which pulls the wire to 0 volts for at least 480 µs. This signal resets all devices on the bus, simply taking the power out from the bus. After that, any device on the bus, shows that it exists with a „presence“ pulse by holding the wire to ground at least 60 µs after the master releases the bus. With following 8-bit command and then data can be sent or received in groups of 8-bits. Each device on the bus has a unique 64-bit serial identification number.

1-wire sensors connection
Data transfer on a 1-wire bus

To find all devices, master send an enumeration command, and an address. For each bit master listens the answer. If slave device has all right address bits it returns a 0. Master uses this simple behavior to search for valid sequences of address bits. An enumeration of 10 or 15 devices finishes very quickly.

A read-time is initiated by master device pulling the 1-wire bus low for a minimum of 1 µs and then releasing the bus. Slave device transmits a 1 by leaving the bus high and transmits a 0 by pulling the bus low.

When transmitting a 0, slave device releases the bus by the end of the time, and the bus will be pulled back to its high idle state by pull-up resistor. Output data from the slave is valid for 15 µs after the falling edge which initiated read-time.

Practice

The DS18S20 digital thermometer provides 9–bit centigrade temperature measurements and has an alarm function with nonvolatile user-programmable upper and lower trigger points. A digital thermometer DS18S20 with a 1-wire communication protocol can be connected with Robotic HomeLab Sensor module external sensor connectors. Sensors's technical properties are following:

  • Power supply: +3…+5 VDC
  • Temperature measurement range: -55…+100 °C
  • Wire length: 2 m
  • Datasheet Link

In the example below, 1-wire temperature sensor takes measurements and displays the results on HomeLab's User Interface board LCD display. With the present configuration and provided example code only 5 sensors can be connected to one bus. Sensors will be found automatically.

1-wire temperature sensor must be connected to sensor board ADC3 pin group. After loading the example program to the controller appears sensors queue number and temperature in Celsius on the User Interface board LCD display. If more than one sensor are connected on the bus, then sensor measurements are displayed in a row. Sensor and power supply type are also displayed. Homelab sensor's type is DS18S20 and power supply type is „externally“. It's possible to connect sensor only with 2 wires, in that case sensor receives it's power supply from data bus and on display „parasite“ is displayed. „ERROR!“ is shown in the display if error occurs, in this case the problem is most likely related with wiring.

Colors of the wires for connecting the sensor:

  • Green - Optional VDD pin. VDD must be grounded for operation in parasite power mode
  • White - Data Input/Output pin. Open-drain 1-wire interface pin. Also provides power to the device when used in parasite power mode.
  • Brown - Ground.

Example code enabling to read the temperature with 1-wire protocol is shown below. It is important to include „onewire.h“ and „onewire.c“ to the program. Sensor-specific code is located in „ds18x20.h“ and „ds18x20.c“ files.

 

#include #include #include #include „onewire.h“ #include „ds18x20.h“ #include #include #include

Sensor queue number and sensor's specific code are stored here extern uint8_t gSensorIDs[MAXSENSORS][OW_ROMCODE_SIZE]; Main program int main( void ) {

uint8_t nSensors, i;
int16_t decicelsius;
uint8_t error;
char s[10];
char sensor_nr[1];

// Pin configuration of the Sensor board's multiplexer.
pin multiplexer_pin = PIN(G, 0);
// LCD display initialization 
lcd_gfx_init();

LCD display clear lcd_gfx_clear(); Switching back light on

lcd_gfx_backlight(true);	

Multiplexer's pin configuration as a output and then switchover it to connect external sensor with the controller.

pin_setup_output(multiplexer_pin);
pin_set(multiplexer_pin); 

// 1-Wire bus configuration. In sensor board the ADC3 pin group is same as PF3.
ow_set_bus(&PINF,&PORTF,&DDRF,PF3);
// Searching for sensors. For variable nSensors is attributed the sum 
// of all found sensors.
nSensors = search_sensors();
while(1) 
{
  error = 0;
  // If no sensors found the error flag is set.
  if ( nSensors == 0 ) 
  {
    error++;
  }
  // All the sensor are displayed starting at the bottom.
  for ( i = nSensors; i > 0; i-- ) 
  {
// Taking the measurements. In case of error, the error flag is set.
if (DS18X20_start_meas(DS18X20_POWER_PARASITE,&gSensorIDs[i-1][0])==DS18X20_OK) 
{
  sw_delay_ms( 750 );
		
  // Measurements are saved in decicelsius. In case of error,
  // the error flag is set.
  if (DS18X20_read_decicelsius(&gSensorIDs[i-1][0],&decicelsius)==DS18X20_OK) 
  {
    // Displaying the word "TEMP".
    lcd_gfx_goto_char_xy(2, 1);
    lcd_gfx_write_string("TEMP");
  	    // Displaying degree sign
    lcd_gfx_goto_char_xy(13, 1);
    lcd_gfx_write_string("C");
    // Making the readings to strings and adding +/-.
    DS18X20_format_from_decicelsius( decicelsius, s, 10 );
    // Displaying the temprerature
    lcd_gfx_goto_char_xy(7, 1);					
    lcd_gfx_write_string(s);
    // Displaying sensors queue number.
    // Firstly it's converted to a string.
    lcd_gfx_goto_char_xy(0, 1);
    sprintf(sensor_nr, "%d", i);
    lcd_gfx_write_string(sensor_nr);
  } 
  else 
  {
    // CRC error (Connection is down)
    error++;
  }
}
else 
{
  error++;
}
  }		
  // Displaying the error messege.
  if ( error ) 
  {
lcd_gfx_goto_char_xy(1, 3);
lcd_gfx_write_string("ERROR!");
error = 0;
  }
  else
  {
lcd_gfx_goto_char_xy(1, 3);
lcd_gfx_write_string("        ");
  }
  sw_delay_ms(500);
}

}

Exercises

The goal is to write a program which executes following task:

Warm-up exercise

  • The value of the resistance of the potentiometer is displayed on the LCD in ohms when the resistance of potentiometer is below 1000 Ω and kilo-ohms when above 1000 Ω. The nominal value of the resistance is 10 kΩ. Results show in the correct units, ohm mark as (Ohm).

=== For beginners =

  1. Measuring the distance to an object. The distance to an object is measured with an IR sensor by pressing the button S1. During the measuring yellow LED is blinked. If the object is beyond 50 cm a green LED is lit and when the object is closer than 50 cm a red LED is lit.
  2. The distance to an object is measured using an UH sensor. The result is displayed on the 7 segment display. If the distance is growing, the displayed value must grow respectively. The scale should be in decimetres (dm).
  3. The value of the NTC temperature sensor is displayed on the LCD in degrees. By pressing the S2 button the units may be selected: Kelvin (K), Fahrenheit (F) and Celsius (C). The temperature is displayed in correct units and symbols.
  4. By using a LDR sensor, rapid changes of light intensity are registered (switching lamps on-off). If the change is rapid, red LED is blinked for 5 seconds. If the light changes smoothly the direction of the change is shown. Green LED means that the light intensity grows and yellow shows that it diminishes.(Suggestion: the value of the sensor does not need to convert the lux, the calculations may be done using the direct ADC value.)
  5. By using a PIR sensor and combined temperature-humidity sensor, create a simple program that shows a room ambient parameters: humidity, temperature and light intensity on the LCD screen when a person entering the room. If a person is leaving, the LCD display is cleaned and the program will enter standby mode.

For advanced

  1. Data recorder. The values of all analogue sensors (potentiometer, thermistor, and the photoresistor) are measured constantly and minimum and maximum values are recorded. By pressing button S1 the user may change the information displayed on the LCD. Displayed must be: name of the sensor (shortly) and present minimum and maximum values.
  2. UH Distance sensor. If the button number S2 is pressed, 10 sequential measurements are taken place in one second. After measuring the average distance to the object in decimetres it is displayed on 7-segment indicator. By pressing button S1, minimum measured value is displayed and by pressing button S3 maximum value is displayed.
  3. Velocity. According to the changing rate of the distance to the object (as measured by infrared or ultrasonic sensor), it is shown with LEDs as follows: slow change – green LED, moderate change – yellow LED and rapid change red LED. The speed may be displayed on the LCD.
  4. By combining IR and ultrasonic distance sensors the distance to the object, velocity of the object and direction of the object are determined. Results are displayed on LCD.
  5. Using the acceleration sensor detect the movement of an object and the direction of movement, which is displayed on a stripe with direction of the center of the LCD. The stripe length corresponds to the absolute value of the acceleration.

 

Questions

  1. How accurate is the digital-analogue converter (ADC) of ATxmega128A1U microcontroller? How small is the minimal change of input voltage which can be measured?
  2. How long takes one ADC process? How is the operating frequency changed?
  3. Which is the the range of input voltage of the ADC? Is it possible to be changed? How?
  4. What is the difference between positive temperature coefficient (PTC) thermistor and negative temperature coefficient(NTC)? What are the advantages of each?
  5. What is the purpose of a voltage divider in a measuring circuit?
  6. Combine a voltage divider, which allows to use an analogue sensor with ATxmega128A1U microcontroller. The maximum output voltage of the sensor is 10 V.
  7. Extra resistors were added to the potentiometer pins and voltage of 5 V were applied on them. How big must be the resistances of extra resistors and the potentiometer so the regulated voltage on the slider of the potentiometer can be regulated between 1 V and 2 V (from one end to the other end)? The current should not exceed 10 mA.
  8. Which parameters of the surroundings have an effect on the functioning of ultrasonic distance sensor and why?
  9. Which light sensitive sensors could be used in a robotics project. Count at least three principal components and explain their differences.
  10. Besides trigonometrical method, how is distance determined by using light? Name at least 3 methods.

Motors

Motors are actuator devices, actually some of them are and those can also be very different, beginning with operating principles and ending with power and size. In robotics mainly electric motors are used. Electrical motor is a device which converts electrical energy to mechanical energy (work). It works on principles of electromagnetism.

There are several ways to classify electrical motors. Most important is to divide them as alternate current (AC) and direct current (DC) motors. In addition, there are electrical motors with brushes and brush-less motors, linear motors and rotary motors, nano-motors and large motors and so on. On the other hand, some of the segmentations are provisional. For example, linear motion is achieved usually using rotary electrical motor, which is integrated into unitary body with screw mechanism and treated so as linear actuator. In this chapter are covered three most common types of electrical motors in robotics: DC motor with permanent magnets, RC servos and stepper-motor.

 

DC motor

Theory

DC motor

Permanent magnet DC motors are very common in different applications, where small dimensions, high power and low price are essential. Due to their fairly high speed, they are used together with transmission (to output lower speed and higher torque).

The perfect graph of relationship between speed (V), current (I), power (P), efficiency (η)and torque (T)of a DC motor.

Permanent magnet DC motors have quite simple construction and their controlling is quite elementary. Although controlling is easy, their speed is not precisely determined by the control signal because it depends on several factors, primarily of the torque applied on the shaft and feeding current. The relationship between torque and speed of a ideal DC motor is linear, which means: the higher is the load on the shaft the lower is the speed of the shaft and the higher is the current through the coil.

Brushed DC motors are using DC voltage and basically do not need special control electronics because all necessary communication is done inside the motor. When the motor is operating, two static brushes are sliding on the revolving commutator and holding the voltage on the coils. The direction of revolving of the motor is determined by the polarity of the current. If the motor must revolve in only one direction, then the current may come through relay or some other simple connection. If the motor has to revolve in both directions, then an electronic circuit called H-bridge is used.

In the H-bridge are four transistors (or four groups) directing the current for driving the motor. The electrical scheme of the H-bridge is similar to the letter H and that is where it gets its name. The peculiarity of the H-bridge is the possibility to apply both directional polarities to the motor. Picture on the side shows the principal scheme of the H-bridge based on the example of the switches. If two diagonal switches are closed, the motor starts operating. The direction of the revolving of the motor depends on in which diagonal the switches are closed. In the real H-bridge the switches are replaced with transistors which are selected according to the current of the motor and voltage.

The working principle of H-bridge used on switches.

H-bridge can also change the direction of rotation than the rotation speed of the motor. There exist also integrated H-bridges, for conducting smaller currents. For higher currents special power MOSFET-s are used. The H-bridge with other electronics is called motor controller or driver.

While the speed of the DC motor is easy to control, there is no guarantee that the desired speed is reached after all. The actual velocity depends on many factors, primarily torque on the output shaft of the motor, current and other motor characteristics. The speed and the output torque of the ideal motor is linearly dependent, i.e. the larger is the output torque, the lower is the speed of the motor, and it consumes more current. This depends on the exact type of motor in case of real motor.

A direct current (DC) motor can be controlled with analog as well as digital signals.

Normally, the motor speed is dependent on the applied voltage at the terminals of the motor. If the motor feed a nominal voltage, it rotates a nominal speed. If the voltage given to the motor is reduced, the motor speed and torque are reduced as well. This type of speed control is also called as analog control. This can be implemented, for example, using a transistor or a rheostat.

DC motors are controlled by microcontrollers, and because microcontrollers are digital devices, it is also reasonable to control the motors digitally. This is achieved by using pulse width modulation (PWM), by switching transistors quickly on - off. The total motor power is something in between standing and full speed. The time of the entire PWM period when transistor is opened, called duty cycle, which is denoted by percent. 0% means that transistor is constantly closed and not conduct, 100% means that transistor is opened and conducts. The PWM frequency should be high enough to prevent vibration of the motor shaft. At low frequencies the motor produces a noise and is therefore used modulating frequency above 20 kHz mostly. However, transistors efficiency is suffering from very high frequencies.

Compared to the analog control a digital control has a number of advantages. The main advantage of microcontroller-controlled systems is that it requires only a single digital output and there is no need for complicated digital-to-analog converter. The digital controlling is also more efficient because less energy is converted into heat.

A simplified control scheme is shown in the next drawing. The control voltage Vc is coming to the microcontroller output pin and switch the transistor Q on-off at a frequency of approximately 20 kHz. When the transistor Q is switched on, then the total current I is going through the motor M. In this case, the transistor behaves as a closed switch and a voltage drop Vq is near 0, and the entire input voltage Vdd remains the engine.

The total power which is passing the transistor can be calculated by the formula:

P = I * V

P = I * Vq, and when Vq ~ 0, then P ~ 0 W

This means that the transistor spend almost no energy in the open state. Similar situation is also the case when the transistor is in the closed state. In this case, there is no current flow through the transistor or the motor. Now the power which is going through the transistor, is calculated as follows:

P = I * Vq, and when I = 0, then P = 0 W

In conclusion, we can say that if the transistor is a switch element on the scheme, then the system efficiency is high and the power used by transistors is low. Compared with a linear (analog) system, where the transistor consumes of the half-open state the same amount of power than the motor, it is a very big energy savings. In practice, there is no lossless system and in fact, the losses occur when the transistor switch one state to other. Therefore, higher losses are occurring when the transistors are switched at higher frequencies.

Practice

The HomLab uses a combined ships to drive DC motors, which includes 2 integrated H-bridges and circuit breaking diodes. The motor is controlled with three digital signals, one of them is operation enabling signal enable and the other two are determining the state of the transistors in the H-bridge. Never can occur that two vertical transistors are opened, because this would short-circuit the power source. This means that the driver is designed as foolproof and only option that can be chosen is which transistor (upper or bottom) of one side of the H-bridge (of “semi-bridge”) is opened. In other words the polarity is selected using two driving signals which is applied to the two ends of the coil of the motor.

The Combo Board of the HomeLab allows connecting up to four DC motors. Basically, for every motor there is a H-bridge which is controlled with two digital output pins of the microcontroller, because the enable pin is constantly high. If both controlling pins have same value, then the motor is stopped if different then it revolves in the corresponding direction. The state of the H-bridge is described in the following table:

Input A Input B Output A Output B Result
0 0 - - The motor is stopped
1 1 + + The motor is stopped
1 0 + - The motor revolves in direction 1
0 1 - + The motor revolves in direction 2

For each motor that is connected to the H-bridge is operated by two of the digital output of the microcontroller. The motor speed is is controlled by timers that generate a continuous PWM signals to the H-bridge, the direction of rotation of the motor is controlled to the second terminal. Motor speed is controlled a relative values from 0 to 255, where 0 means that the motor is standing and 255 is the maximum moving speed of the motor. The following code describes a function’s, which are described in the HomeLab II (ATmega2561) library to control DC motors.

The setup of the pins driving pins static pin dcmotor_pins[4][2] = { { PIN(B, 7), PIN(B, 4) }, { PIN(D, 1), PIN(D, 0) }, { PIN(D, 7), PIN(D, 6) }, { PIN(D, 5), PIN(D, 4) } }; static int motorindex[4][2] = { { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 } }; Initializing a PWM to chosen motor void dcmotor_drive_pwm_init(unsigned char index, timer2_prescale prescaler) {

	unsigned char i, pwm;

pin_setup_output(dcmotor_pins[index][0]);

pin_setup_output(dcmotor_pins[index][1]);

motor[index] = 1;

	pwm = PWMDEFAULT;

Starting all channels for(i=0 ; i>3) dcmotor_drive_pwm(1, 1, speed/8); dcmotor_drive_pwm(2, 1, 128); } } ==== Servomotor ==== Necessary knowledge: [HW] User Interface Module, [HW] Combo module, [AVR] Counters/Timers, [AVR] Analog-to-digital Converter, [LIB] Motors, [LIB] Analog to Digital Converter === Theory === [RC servo motor] [The relationship between width of the signal and position of Servo PWM.] RC (radio-controlled) servo-motors are very common actuator devices in robotics and model building. RC servo motors are consisting of small DC motor, reduction gear and control logic device. Usually the rotor of the servo motor moves to a certain position and tries to maintain that position. The position of the rotor depends of the control signal received by the servo motor. Depending on the type of the motor, the maximum revolving angle of the motor may differ. Servo motors that revolve constantly are rare. In this case, the control signal determines not the revolving angle but the speed of revolving. Servo motor “hack” is also quite common. This makes the position determining servo motor to constantly revolving servo. In this case the feedback potentiometer is replaced by two fixed resistors and the mechanical resistor that prevents full rotations is removed from the gear. A very important characteristic of servo motors is its power-weight ratio. The controlling signal of servo motor is specific pulse with modulated signal (PWM), where width of the pulse determines the position of the rotor. The period of the signal is 20 ms (50 Hz) and the width of the high period is 1 ms – 2 ms. 1 ms marks one extreme position and 2 ms marks the second one. 1,5 ms marks the middle position of the servo motor’s rotor. Traditional RC servo motor is also known as analogue-servo motor. It is because in the last decade so called digital servo motors were becoming common. The difference between those two is that in analogue servo motor the motor is controlled by the same 50 Hz PWM input signal. In digital servo motor the motor is controlled by a microcontroller with much higher frequency signal. The input signal is the same in the digital servo motor but higher modulation frequency of the motor enables much more precise and faster position determining. === Practice === On the board of module of motors of the HomeLab are two or four plugs for connecting RC servo motors. The PWM ends of the plugs are connected to the pins of the microcontroller, which alternative functions are outputs of comparing units of the timer. Timer is capable of producing PWM signal and due to that the control of motors is very simple in the program. Only difficulty is set-up of the timer. The timer must be set up in PWM production mode, where the maximum value of the timer is determined with ICR register. With the maximum value changed in the program and in the pace divider of the timer, the precise PWM frequency for controlling the servo motor can be determined. With the comparison register of the timer, lengths of both high semi periods of PWM signal can be determined. The timers have special comparing units which are monitoring the value of the counter and in case it remains equal with the value of the comparison register they change the output value of comparing units. The following is the program code of the servo motor control library of the HomeLab. For the purpose of functionality, it uses parameters for timers which are determined with macro functions. For example, the period is found using F_CPU constant, which marks the clock rate of the microcontroller. When using macros, there is no need to calculate the parameters of timer for different clock rates and the compiler converts the operations with macros to constants anyway, so the program memory is not growing and does not demand more time. The following example of library is for HomeLab II (ATmega2561). The value of the timer (20 ms)for achieving the full period of PWM F_CPU is the clock rate of the microcontroller which is divided with 50 Hz and 8 #define PWM_PERIOD (F_CPU / 8 / 50)

Middle position of PWM servo (5 ms / 20 ms) Middle position is 15/200 of full period #define PWM_MIDDLE_POS (PWM_PERIOD * 15 / 200)

Factor for converting the percents (-100% to 100%)to periods +1 is added to ensure that semi periods would reach to the boundaries of 1 ms and 2 ms or a little over #define PWM_RATIO (PWM_PERIOD / 20 / 2 / 100 + 1)

Set-up of the pins static pin servo_pins[2] = { PIN(B, 5), PIN(B, 6) }; Preparing the servo motor for working void servomotor_init(unsigned char index) {

// The pin of PWM signal for output
pin_setup_output(servo_pins[index]); 

Setup of timer 1 Prescaler = 8

// Fast PWM mode, where TOP = ICR
// OUTA and OUTB to low in comparisson
timer1_init_fast_pwm(
	TIMER1_PRESCALE_8,
	TIMER1_FAST_PWM_TOP_ICR,
	TIMER1_FAST_PWM_OUTPUT_CLEAR_ON_MATCH,
	TIMER1_FAST_PWM_OUTPUT_CLEAR_ON_MATCH,
	TIMER1_FAST_PWM_OUTPUT_DISABLE);

Determining the period by maximum value timer1_set_input_capture_value(PWM_PERIOD); } Determining the position of the servo motor The parameter of the position is from -100% to +100%. void servomotor_position(unsigned char index, signed short position) { switch (index) { case 0: timer1_set_compare_match_unitA_value( PWM_MIDDLE_POS + position * PWM_RATIO); break; case 1: timer1_set_compare_match_unitB_value( PWM_MIDDLE_POS + position * PWM_RATIO); break; } } The example program uses described functions of the library of the HomeLab. In the beginning of the program the first servo motor’s PWM signal generator is started with the servomotor_init function. The value of the position of the servo motor is obtained from the channel of the analogue-digital converter, where a potentiometer on the board of sensors is connected. To get the range -100 % - +100 % necessary for controlling the servo motor, half of the maximum (512) is subtracted of the ADC value and the result is divided with 5. The result is +/- 102, but small inaccuracy does not count because servo motors also differ by the relation of the PWM signal and revolving angle. Final PWM‘s semi period’s width in applications has to be determined using test-and-error method. Also the remote controls of RC models have corresponding opportunities for precise setup (trim function). When the program is started the rotors position of the servomotor is changed according to the position of the potentiometer. Testing program of the motors module of the HomeLab kit #include #include

Main program int main(void) { short position; Set-up of the ADC

adc_init(ADC_REF_AVCC, ADC_PRESCALE_8);
// Set-up of the motor
servomotor_init(1);
// Endless loop
while (1)
{
	// Reading the position of the potentiometer and 
	// converting the range of
	// the servo motor
	// For HomeLab II ADC must be read for the corresponding channel, 
	// and use the following formula:
	// position = ((short)adc_get_value(3) - (short)512) / (short)5;
	position = ((short)adc_get_value(15) / 10) - 102 ;
	// Determining the position of the servo motor
	servomotor_position(1, position);
}

}

Stepper motor

Theory

Stepper-motor

Stepper-motors are widely used in applications which demand accuracy. Unlike DC motors, stepper motors do not have brushes nor commutator – they have several independent coils, which are commutated with exterior electronics (drivers). Rotating the rotor is done by commutating coils step by step, without feedback. This is one of the faults in stepper motors – in case of mechanical overloading, when the rotor is not rotating, the steps will be mixed up and movement becomes inaccurate. Two types of stepper motors are distinguished by coils: unipolar and bipolar stepper motors. By construction three additional segments are considered:

  • Variable Reluctance Stepper (high accuracy, low torque, low price)
  • Permanent Magnet Stepper (low accuracy, high torque, low price)
  • Hybrid Synchronous Stepper (high accuracy, high torque, high price)

Variable reluctance stepper motors have toothed windings and toothed iron rotor. The largest pulling force is when the teeth of both sides are covering each other. In Permanent magnet stepper motor,just like the name hints, are permanent magnets which orientate according to the polarity of the windings. In hybrid synchronous steppers both technologies are used.

Depending on the model of stepper motor, performing one full rotation (360 degrees) of the rotor, demands hundredths of steps of commutations. For stable and smooth movement, appropriate control electronics are used which control the motor according to its parameters (inertia of the rotor, torque, resonance etc.). In addition to control electronics different commutating methods may be applied. Commutating one winding in a row is called Full Step Drive and if the drive is alternated between one and two windings it is called Half Stepping. Cosine micro stepping is also used, allowing specially accurate and smooth controlling.

Unipolar stepper-motor

Unipolar-stepper motor has 5 or 6 leads. According to the scheme of the motor only ¼ of the windings is activated. Vcc lines are usually connected to the positive power supply. During commutation the ends of windings 1a, 1b, 2a and 2b are connected through transistors only to the ground and that makes their control electronics fairly simple.

Bipolar stepper-motor

The windings of an unipolar-stepper motor
The windings of a bipolar stepper-motor.

Bipolar stepper motor differs from unipolar stepper motor by having the polarity of the windings altered during the commutation. Half of the windings are activated together, this allows to gain higher efficiency than unipolar stepper motors. Bipolar stepper motors have four leads, each connected to a different half-bridge. During commutation half-bridges are applying either positive or negative voltage to the ends of the windings. Unipolar motors can be started using bipolar driver: just connect lines 1a, 1b, 2a and 2b of the windings (Vcc will be not connected).

The commutation necessary for controlling stepper-motors with windings at full step mode and half step mode is displayed in the table below. Since in drivers for uni-polar stepper motors only opening of the transistors takes place, the steps are marked by 0 and 1. Controlling of bipolar stepper motors may need more signals and therefore the steps are marked using the polarity of the driver outputs:

Unipolar Bipolar
Step 1A 2A 1B 2B 1A 2A 1B 2B
Full step
1 1 0 0 0 + - - -
2 0 1 0 0 - + - -
3 0 0 1 0 - - + -
4 0 0 0 1 - - - +
Half step
1 1 0 0 0 + - - -
2 1 1 0 0 + + - -
3 0 1 0 0 - + - -
4 0 1 1 0 - + + -
5 0 0 1 0 - - + -
6 0 0 1 1 - - + +
7 0 0 0 1 - - - +
8 1 0 0 1 + - - +

Practice

The Combo Module has a H-bridges to control bipolar stepper motors and the transistor matrix for unipolar stepper motor.

There are functions bipolar_init and unipolar_init in the library of the HomeLab which sets the pins as output and functions bipolar_halfstep and unipolar_halfstep executes revolving by determined half steps. The commutation is done by the table of half steps, but more complex bit operations are used. Unipolar stepper motor is connected to a separate connector Unipolar Stepper, bipolar stepper motor is connected to a DC motor connector, where one of the bipolar motor occupies driver pins of two DC motor. The following code section is HomeLab II (ATmega2561) library functions.

Preparing for controlling the bipolar stepper motor void bipolar_init(void) { DDRB |= 0x0F; PORTB &= 0xF0; } Moving the bipolar stepper motor by half steps void bipolar_halfstep(signed char dir,

unsigned short num_steps, unsigned char speed)

{

unsigned short i;
unsigned char pattern, state1 = 0, state2 = 1;
// Insuring the direction +- 1
dir = ((dir < 0) ? -1 : +1);
// Execution of half-steps.
for (i = 0; i < num_steps; i++)
{		
	state1 += dir;
	state2 += dir;
	// Creating the pattern
	pattern = (1 > 1) ) |
	          (1 > 1) );
	
	// Setting the output.
	PORTB = (PORTB & 0xF0) | (pattern & 0x0F);
	// Taking a break to wait for executing the step
	sw_delay_ms(speed);
}
// Stopping the motor
PORTB &= 0xF0;

}

Usage of the functions is demonstrated by the example program which rotates the motor alternately to one direction and then to the other direction 200 half steps. The speed of rotating the motor is determined by the length of the brakes made between the steps. If the break is set to be too short, the motor can not accomplish the turn due to the inertia of the rotor and the shaft does not move.

The test program for the stepper motor of the HomeLab #include Main program int main(void) {

// Set up of the motor
unipolar_init(0);
	
// Endless loop
while (true)
{
	// Turning the rotor 200 half steps to one direction 
	// at speed of 30 ms/step.
	unipolar_halfstep(0,+1, 2000, 30);
	// Turning 200 half steps to the other direction 
	// at speed 30 ms/step.
	unipolar_halfstep(0,-1, 2000, 30);
}

}

Exercises

The goal is to write a program which is able to perform tasks described below.

Warm up exercise

  • Controlling the DC motor using buttons of a User Interface module. By pressing S1 button, the motor turns clockwise. By pressing S3 button, the motor revolves clock-counterwise. By pressing S2, the motor is stopped.

For beginners

  1. DC motor control. Movement of a robot is simulated, by using DC motor and touch sensors. Touch sensors are the buttons S1, S2 and S3 of the User Interface module. The motor is controlled by pressing the buttons. S1 and S2 pressed separately stops the engine for two seconds and then start motor again. If both buttons are pressed, then the motor is stopped until the buttons are released. (For a robot, similar scheme should be implemented to control two separate motor).
  2. DC motor accelerates when S1 is pressed down and holds achieved speed when the button is released. By holding S2 pressed down, the motor decelerates smoothly. By pressing button S3, the motor stops instantly.
  3. Servo motor, the servo motor is controlled via the buttons of the User Interface module. By pressing down S1 the servomotor moves one step to the right. By pressing down S3, the servo motor moves one step to the left and S2 makes the servo motor to move to the initial (middle) position. The position of the servo motor is displayed live on the 7 segment display (each number corresponds to 10 degrees of the turn: middle position equals 5).
  4. Radar, UH sensor based radar is simulated. Sensor is installed to the lever of the servo motor. The lever of servo motor is moving constantly form one extreme position to the other. If there happens to be an object in closer range than 0,5 meters of the sensor, then the servo motor is stopped for 5 seconds and by signaling a LED that detection of the object is announced. After 5 seconds of flashing of the LED, scanning continues.
  5. Stepper motor, after each pressing on the buttons S1 and S3 it rotates 50 steps, accordingly clock wise and anti clock wise.

For advanced

  1. Tracking an object. By using ultrasonic distance sensor, which is installed on the lever of the servo-motor, the servomotor has to track a bypassing object. The motor turns according to the movement of the object so that the object is all the time in the middle of the tracking sector of the sensor.
  2. Using a stepper motor, make a second dial of the analog clock. The motor must be make exactly 60 steps on one complete rotation. Movement should be stepped and not smooth.
  3. Acceleration, the program allows changing the acceleration/deceleration of the stepper motor. Use linear speed slopes which can be easily identified at visual inspection. Longer movements have to follow the following scheme: acceleration –> steady speed –> deceleration.
  4. Design a PID regulator (or its simplified form) for a DC motor. NB! This exercise demands a motor with feedback (encoder).
  5. DC motor. The DC motor is controlled via the buttons of the User Interface module. By pressing down S1 the motor moves one step (x encoder pulses) to the left. By pressing down S3, the motor moves the same amount of steps to the back. The motor rotates exact amount of a predetermined steps, regardless of a torque applied to the shaft (in the case where applied torque is less than the engine maximum output torque).

Questions

  1. For what is the H-bridge used? On what principle is it working?
  2. How is the position of the shaft of RC servo motor determined?
  3. What is the main difference between unipolar- and bipolar-stepper motors?
  4. How can half step and micro step modes of stepper-motor be applied? Give an example.
  5. How is the rotation speed of a DC motor controlled? Give an example.
  6. Which PWM working cycle is needed to achieve DC motor's shaft rotation speed 70% of nominal?
  7. How is the direction of motor's rotation determined when encoder is used?
  8. How can a DC motor be electrically slowed?
  9. What happens if the scheme of commutation of a stepper-motor is changing too fast?
  10. Is it possible and if yes, how is it possible to use dynamical braking?

Communication

Data interfaces

With microcontrollers it is possible to control actuators, read the values of sensors and many other stuff, but always stays the need for connecting all kind of devices, which does not allow to communicate by sending simple digital signals. The reason may be: there are too many control signals needed to control the device or there is too much data to be sent. That is why there are many data interface standards developed for microcontrollers or for every kind of electronics. The standards are determining the electrical parameters of the signals and the rules of transmission of the signals (the protocol).

One simple example of a protocol is the Morse code, where the information is transmitted using peeps and pauses and varying their lengths. Digital data transmitting protocols are functioning similarly; in there the info is transmitted as bit values and depending on the interface also as modulated form. Different data transmitting interfaces with their protocols have been created according to the need but the data quantities have always grown and new methods have been constantly added. The situation in the data transmission between the electronics components is calmer. There are I²C, SPI and UART interfaces used already for a long time. More traditional intersystem transmission interfaces are RS-232, RS-485, LIN and CAN, but many microcontrollers are already produced with USB, Ethernet and wireless ZigBee interfaces. This chapter is focusing on the data transmitting by using RS-232 interface.

/home/www/roboticlab/homelab_data/pages/en/examples/communication/uart.txt— MISSING PAGE — /home/www/roboticlab/homelab_data/pages/en/examples/communication/rs232/linux.txt— MISSING PAGE — /home/www/roboticlab/homelab_data/pages/en/examples/communication/usb.txt— MISSING PAGE —

ZigBee

The necessary knowledge: [HW] Controller module, [AVR] USART, [LIB] Serial Interface,
[LIB] Graphic LCD

Theory

XBee module.

ZigBee is a specification for high level communication protocols using small, low-power digital radios based on an IEEE 802.15.4-2003 standard for personal area networks. ZigBee is designed for devices which require simple wireless networking and don't need high data transfer rate. These devices might be for example sensor network, information displays, home- and industrial automatic systems, etc. Main benefit compared with Bluetooth is lower power demand, quick respond from sleep to awake and cost. ZigBee works in most cases at 2.4 GHz radio band frequency with data transmission rates from 20 to 900 kb/s. ZigBee protocol supports different types of network like star, tree and generic mesh. Network nodes can have different roles like coordinator, router or end device.

Based on ZigBee wireless modules direct connection between two devices or more complicated network can be set up. In figure below a sensor network transferring measurement to user interface is illustrated.

Practice

Robotic HomeLab Communication board has a connector for wireless modules, including ZigBee module XBee from Maxtream. Communication between module and the controller is realized over UART interface. At first device is set to API mode by sending command “+++„. Further configuration is done with standard AT command found on device manual. When communication between two modules has been established, device will be returned to transfer mode.

Example code above is searching surroundings for other Zigbee devices and found device addresses devices are displayed on Homelab User Interface module LCD display. Global address 0000FFFF has a special meaning - info sent to this address is received by all available devices. In the example code, after searching other devices one is connected and devices start to sending a button pressing event to each other by showing the result on the other device LED.

#include #include #include #include

Adding ZigBee module support #include Determination of the USART interface usart port = USART(1);

LED and button pin setup pin leds[3] = { PIN(C, 5), PIN(C, 4), PIN(C, 3) }; pin buttons[3] = { PIN(C, 0), PIN(C, 1), PIN(C, 2) }; Max numbers of ZigBee modules in network + broadcast address +1 #define ZIGBEE_MAX_NODES 4

int8_t wait_button(uint16_t ms);

Address array of other Zigbee modules found in network zigbee_node_t nodelist[ZIGBEE_MAX_NODES]; int main(void) { uint8_t adr = 0; Acquired module order list

  // LED and buttons I/O ports configuration
  for (int i=0; iaddress64l);

  // Confederate ZigBee to send info for chosen ZigBee module's node,
  // in this case to first [0]
  // (What port is using, where takes the address)
  zigbee_set_destination(port, &nodelist[adr]);
  // Displays info on LCD
  lcd_gfx_goto_char_xy(0, 0);
  lcd_gfx_write_string("  ZigBee demo");
  lcd_gfx_goto_char_xy(0, 1);
  lcd_gfx_write_string("Button1: LED1");
  lcd_gfx_goto_char_xy(0, 2);
  lcd_gfx_write_string("Button2: LED2");
  // Save the state of previous button to avoid multiple button pushes at once.
  // At first is -1 ie none of the buttons is pushed.
  int8_t previousButton = -1;
  // Endles-loop for communicating between modules
  while (true)
  {
      int8_t button;	//variable for saving button pushes  
      // wait 1 millisecond for button
      button = wait_button(1);
      // if in last cycle button wasn't pressed but now is 
      if (previousButton == -1 && button != -1)
      {
          // Convert button's index by adding A
    // and sent it to other modules
          // A is for first button, B for second and so on
          usart_send_char(port, 'A' + button);
      }
      // read from USART
      if (usart_has_data(port))
      {
          // Read bait, convert to leds array index
    //and change the output.
          pin_toggle(leds[usart_read_char(port) - 'A']);
      }
      // remember what button was pressed
      previousButton = button;
  }

}

Wait for button to be pressed for ms milliseconds. If button is pressed returns the queue number of the button int8_t wait_button(uint16_t ms) {

  // By default -1 means, that no button is pressed.
  int8_t button_nr = -1;
  uint16_t counter = 0;
  do
  {
      // check if one of the buttons is pressed
      for (uint8_t i=0; i

/home/www/roboticlab/homelab_data/pages/en/examples/communication/bluetooth/btbee.txt— MISSING PAGE — /home/www/roboticlab/homelab_data/pages/en/examples/communication/i2c.txt— MISSING PAGE —

Ethernet

Theory

Ethernet is summarizing networking technologies for LANs. It was introduced first in 1980 and later standardized as IEEE 802.3 in 1985.

When talking about Ethernet standards, those are tightly connected with the OSI physical layer. Ethernet provides service up to and including the data link layer. As transfer medium, Ethernet started with coaxial cables, with the 10BASE5 standard, later replaced by twisted pair and after that by fiber optic links.

The possible transmission rate with Ethernet started with 10 megabits per second, up to currently 100 gigabits per second. Most computer networks are currently using 100 Mbit/s infrastructures, tending to 1GB/s.

A system utilizing Ethernet divides a networking (data) stream into small pieces, called frames. Each frame needs to contain the sender (source) and receiver (destination) addresses, the MAC adresses and data for error checking. In the middle section, an Ethernet frame is carrying data including headers from other protocols, like the Internet Protocol (IP protocol). The error checking is realized by a 32-bit cyclic redundancy check that is able to detect errors in the data.

A 802.3 Ethernet frame consists of a 8byte long preamble, with bit synchronization information, followed by a 1 byte sequence (“10101011”) as a Start Frame Delimiter. The next two times six bytes are carrying the destination and source address (each usually 48 its long).

Next 2 bytes are specifying the length of the data segment, followed by the so called Data Unit (bytes 46 to 1500). The 802.3 has a maximum of 1500 MTU (the maximum transmission unit), Ethernet with LLC and SNAP and PPPoE only 1492. For other types of Ethernet, the MTU (maximum bytes) can be also from 1500 to 9000. Next 4 bytes are for the error detection of corrupted data. This check is an 802.3 version of CRC. This 32 bit code has an algorithm applied to it which will give the same result as the receiver of the link, provided that the frame was transmitted successfully.

Practice

RFID moodulid

RFID on tehnoloogia andmevahetuseks raadiolainete kaudu lugeja ja elektroonilise identiteedi vahel, mis on paigaldatud mõne objekti külge identifitseerimise ja jälgimise eesmärgil. RFID võimaldab iga objektiga siduda unikaalse ID-numbri. Passiivsed identiteedid, millel pole patareid, on võimalik lugeda möödumisel küllalt lähedalt lugejast.

Mifare SL031 RFID moodul

Mifare RFID moodul on kõrgsageduslik RFID lugeja, mis töötab sagedusel 13,56 MHz. Samal sagedusel töötvad ka mitmed Eesti koolides ja ettevõtetes kasutatavad id-kaardid ning RFID-nööbid. Moodul SL031 ühendatakse kontrolleriplaadiga järgmiselt: VCC – toide + 3.3 V (sideplaadi Xbee liidesest või kontrolleriplaadi ühendusribast), seda tuleb kindlasti jälgida, et mooduli toiteks mitte suuremat toitepinget kasutada! Siiski mooduli andmeside viigud taluvad ka + 5 V pinget. IN – energia säästmiseks saab RFID-mooduli saata uinunud olekusse. Selleks saadetakse talle käsk 0x50. RFID-moodul ärkab üles langeva frondi peale IN sisendis. TXD – ühendada kontrolleri RXD viiguga (nt. PE0 USART0 kasutamisel suhtlemiseks) RXD – ühendada kontrolleri TXD viiguga (nt. PE1) OUT – see väljund näitab, et mõni ID on detekteeritav (kaart mooduli ligidal, väljund all) või mitte (kaarti pole, väljund üleval) GND – maaühendus

USART0 kasutamisel RFID mooduliga suhtlemiseks ei tohi RFID mooduli TXD/RXD viigud ISP programmeerimise ajal olla sideplaadiga ühendatud, sest siis tekib konflikt ja programmeerimine ei õnnestu.

USART seaded SL031 puhul on vaikimise 115200-8-N-1-N. Arvutiga ühendamise puhul, kui RFID-mooduliga suhtlemiseks kasutatakse USART0 liidest, siis jumperid parempoolsel piikribapaaril tuleb tõsta Xbee pealt RS232_2 peale ja arvuti COM port ühendada sideplaadi RS232_2 pistikusse.

Andmevahetuse formaat kontrolleri ja RFID-mooduli vahel koosneb mitmest baidist, mis on kindlas järjekorras. Esimene bait on alati sama (kontrollerist saatmise puhul 0xBA). Teine bait näitab, mitu baiti veel pärast seda saadetakse ja seda on näiteks võimalik kasutada andmevahetuse jälgimiseks, et teada, millal andmed on saadetud. Viimane bait on kontrollsumma, mille järgi saab veenduda vastuvõetud andmete veatus ülekandes. Moodulile saatmiseks on erinevaid käske, mis kirjutavad/loevad andmeid mälus, panevad selle näiteks toite säästmiseks magama jne.

Näiteprogramm saadab iga sekundi järel käsu RFID moodulile, et teada, kas sellel on mõni ID kaart avastataval ligidusel. Kui on, siis kuvab kaardi unikaalset ID-d tablool. Andmevahetuse iga bait on 16-süsteemis arv/kood, mis tuleb ekraanil kuvamiseks teisendada ASCII tähemärkideks.

Mifare SL031 näitekood

#include #include #include #include

usart port = USART(1); Mifare RFID ühenduseks Käsk moodulile - kaardi valimine preamble, len, command, data, checksum char SL031CMD_SelectCard[] = {0xBA,0x02,0x01,0xB9}; void hex_to_ascii(char *mass, char byte); int main (void) { char resp[14]; char str[4]; int a = 0; int bnr = 4; USART1 setup

  usart_init_async(port,
             USART_DATABITS_8,
                   USART_STOPBITS_ONE,
                   USART_PARITY_NONE,
                   USART_BAUDRATE_ASYNC(115200));
  // LCD ekraani algseadistamine
  lcd_gfx_init();
  // Taustavalgustuse tööle lülitamine
  lcd_gfx_backlight(true);
  // Ekraanile teksti kirjutamine
  lcd_gfx_goto_char_xy(3, 0);
  lcd_gfx_write_string("RFID Demo");
  lcd_gfx_goto_char_xy(0, 2);
  lcd_gfx_write_string("ID: ");
  while (1)	//infinite loop
  {
      // Saada käsk RFID moodulile
      usart_send_string(port, SL031CMD_SelectCard);
      
      // kuni vastuse andmebaidid kohal
      while (a < bnr)
{
	// loeb USART-ist andmeid ja salvestab
	if (usart_try_read_char(port, &resp[a]))
	{
	     // järgmine bait
                   a++;
                   // II bait näitab, mitu baiti veel tulemas on
                   if (a == 2) bnr = resp[1] + 2;
	}
}
// kui ID puudub - "no tag" vastus
if (resp[3] == 0x01)
{
	// kirjuta seda
	lcd_gfx_goto_char_xy(4, 2);
    	lcd_gfx_write_string("puudub   ");
}
// ID on olemas ja loetav
else
{
	// vaata ainult ID baite
	for (a=4; a 0x0F)
{
	high++;
	byte -= 0x10;
}
// esimene numbrikoht, hex teisendada ASCII-ks
mass[0] = high + 0x30;
// kui tähemärk
if (mass[0] >= 0x3A) mass[0] += 0x07;
// teine numbrikoht, hex teisendada ASCII-ks
mass[1] = byte + 0x30;
if (mass[1] >= 0x3A) mass[1] += 0x07;
// stringi terminaator
mass[2] = 0x00;

}

Parallax RFID moodul

Parallaxi RFID moodul on madalsageduslik RFID lugeja, mis töötab sagedusel ~170 kHz.

Parallax RFID näitekood

Järgnev kood kasutab RFID lugejat ja LCD ekraani.

RFID reader with Interstudy ATmegal28 board Reader pins : Enable - PD3, Serout - PD2 (RXD1) Reads and displays ID Includes #include #include #include „lcd.h“ #include „pin.h“

Configuration #define RFID_BAUDRATE 2400 #define RFID_BAUD_VALUE [3]) - 1) #define RFID_ENABLE PORTPIN(D, 3) #define RFID_RX PORTPIN(D, 2) #define LED_GREEN PORTPIN(C, 3) #define LED_DEBUG PORTPIN(B, 7) Display initialization void display_init(void) {

lcd_init(LCD_DISP_ON);
lcd_clrscr();
lcd_puts("  RFID reader\n waiting for ID");

}

Write ID on display void display_write_id(char *id) { lcd_gotoxy(0, 0); lcd_puts(„ID: “); lcd_puts(id); } UART configuring void uart_setup() {

// Setup serial interface
SET_BIT(UCSR1B, RXEN);   // Activate RX only
SET_BIT(UCSR1C, UCSZ0);  // 8 data bits, 1 stop bit, no parity
SET_BIT(UCSR1C, UCSZ1);
// Set baud rate
UBRR1L = (RFID_BAUD_VALUE & 0xFF);
UBRR1H = (RFID_BAUD_VALUE >> 8);

}

Wait for UART incoming data void uart_wait_rx() { while (!IS_BIT_SET(UCSR1A, RXC)) { } } Read UART data inline unsigned char uart_read() {

return UDR1;

}

RFID interface initialization void rfid_init(void) { Setup UART

uart_setup();
// Setup enable and RX pin
pin_setup_output(RFID_ENABLE); 		
pin_setup_input(RFID_RX);

}

RFID ID reading void rfid_read_id(char *id) { enum States { BEGIN, DATA, END } state = BEGIN; unsigned char data; unsigned char digits = 0; Enable RFID with low signal

pin_clear(RFID_ENABLE);
// Cycle until tag ID received
while (1)
{	 

Wait for data uart_wait_rx(); data = uart_read(); Toggle debug indicator

	pin_toggle(LED_DEBUG);
	// What's present state and what's next ? 
	switch (state)
	{
		// Begin state - we expect start byte (0x0A)
		case BEGIN:
			// Got the start ?
			if (data == 0x0A)
			{
				state = DATA;
				
				// Disable RFID
				pin_set(RFID_ENABLE);
			}
			break;
		// Data state - we expect 10 bytes of ID
		case DATA:
			// Fill ID string
			id[digits++] = data;				
			// All digits arrived ?
			if (digits == 10) state = END;
			break; 
		// End state - we expect end byte (0x0D)
		case END:
			// Got the end ?
			if (data == 0x0D)
			{
				// Terminate the string
				id[digits] = '\0'; 
				// All done - return
				return;					
			}
			// Any other case - restart
			else
			{
				state = BEGIN;
				// Enable RFID with low signal
				pin_clear(RFID_ENABLE);
			}
			break; 			
	}
}

}

Main function int main(void) { char id[11]; Initialization

display_init();
rfid_init();
// Setup indicator pins
pin_setup_output(LED_GREEN); 
pin_setup_output(LED_DEBUG);
	

Endless loop while (1) { Turn off green LED

	pin_set(LED_GREEN);
	// Read RFID tag ID
	rfid_read_id(id);
	// Light green LED
	pin_clear(LED_GREEN);
	// Display ID	
	display_write_id(id);		
}

}

Exercises

The goal is to write a program which is able to perform tasks described below.

Warm up exercise

  • To the computer is sent a number with grows once in a second. The number must be in a form of text and end with a row changing sign (\n).

For beginner

  1. For the commands (letter signs) which are coming through RS-232 interface from a computer are being waited. Command “R” lights green LED, “K” lights yellow LED and “P” red LED. “R” is switching all LEDs off.
  2. If a button is pressed, the name of the corresponding button (S1, S2, S3) is received in the computer through the RS-232 interface.

For advanced

  1. The communication between two RS-232 controllers. If a button is pressed, the controller transmits to the controller the number of the button. When the number is received the status of a corresponding LED is changed. '1' → green, '2' → yellow, '3' → red. Requires two sets of controllers, but the software is identical for both controllers.
  2. Make a “teletype” – device, which allows changing text messages between two controllers through RS-232 interface. Use LCD for displaying the messages. On the first row must be seen inserted message and on the second the last received message. For inserting the message a potentiometer and/or buttons may be used.

Questions

  1. Describe the UART package.
  2. What is the baud rate?
  3. What is the difference between full- and half duplexes.
  4. Find at least 5 different sensors which are using serial interface.
  5. What is the difference between UART and USART interfaces? Which is faster?
  6. How is the SPI interface working?
  7. Name interfaces, which enable connecting at least 100 devices to a single bus.
  8. Name different topologies and explain their differences.
  9. On what voltage level are RS-232 and UART connections happening?
  10. How long time takes to transmit 1 MiB at the baud rate of 9600 bps, when there is 8 data-bits, 1 stop-bit and not parity control?

Data storage

EEProm

SD Card

Teooria

Standardsuuruses SD kaart altvaates (Sinine). Lisaks mikro SD kaart ja selle standardsuuruses adapter.

Secure Digital (SD) on mälukaardi formaat, mille töötas välja SD Card Association (SDA) kasutamiseks kaasaskantavates seadmetes. SD kaart töötab 3,3 V tööpingega. Kaartiga suhtlemiseks saab kasutada kaarti enda SD nimelist liidest ja ka SPI siini. Viimane on hea võimalus kasutada SD kaarti lihtsamates süsteemides.

SD kaart on iseenesest suur hulk mälupitte, mida saab küll muuta, aga muud seadmed ei oska salvestatud andmetega seljuhul midagi peale hakata. Probleemi lahendamiseks kasutatakse failisüsteemi, mis annab võimaluse töötada kogu kaardi mälumaatriksi asemel failidega. Failisüsteemi üks tähtsamaid ülesandeid on organiseerida loogilisi faile füüsilisel salvestusseadmel. Salvestusseadmel olev ruum on jaotatud sektoriteks, mille suurus on enamasti 512 baiti. Kuna failisüsteemil on otstarbekas töötada suuremate üksustega, grupeeritakse sektoreid klastriteks. Klaster on mingi täisarvuline hulk järjestikuliselt asuvaid sektoreid. Suurema klastri kasutamisel väheneb suuremate failide puhul fragmentatsioon, kuid väiksemate failide puhul suureneb raisatud ruum, kuna osa klastreid jääb ainult osaliselt täidetuks.

Portatiivsetel mäluseadmetel ja mälukaartidel on laialt levinud FAT (File Allocation Table) failisüsteem, mida toetavad kõik enamlevinud operatsioonisüsteemid. FAT failisüsteemi failipaigutustabel sisaldab iga kettal oleva faili algusklastri kannet, mis omakorda sisaldab viita järgmisele failiga seotud klastrile ja nii edasi, kuni faililõpu klastrini. FAT-i koral on klastrid adresseeritud n-bitiste kannetega aadressiruumi tabelisse, kus n on sõltuvalt FAT-i versioonist 12 (FAT12), 16 (FAT16) või 32 bitti (FAT32). Seega vanemate FAT versioonide korral muutusid suurte kettamahtude korral klastrid mahult suureks ja seega kettamahu kasutamine ebaeffektiivseks.

Praktika

Kodulabori Kontrollermooduli plaadil on pesa Micro SD mälukaardi sisestamiseks. Ühendatud on see samale SPI siinile koos etherneti kontrolleriga.

Kodulabori teegis on SD kaardiga suhtlemiseks kaks kihti. Esimene ketta kiht on seotud otseselt kettaga suhtlemise ja initsialiseerimisega. Lisaks paiknevad seal kettale kirjutamise ja lugemisega seotud funktsioonid. Teine failisüsteemi kiht suhtleb esimese kihiga ja võimaldab failidega seotud toiminguid. Toetatud ja testitud on FAT12, FAT16 ja FAT32 failisüsteemid.

Kodulabori teegis oleva FatFs failisüsteemi paketiga on võimalik lähemalt tutvuda siit.

Järgmine näide demonstreerib tekstifaili lugemist ja kirjutamist. Nupule S1 vajutades initsialiseeritakse ketas ja failissüsteem. Nupu S3 vajutamine loob kettale kausta, kuhu omakorda luuakse fail. Faili kirjutatakse ka sisu. Nupp S2 kuvab tekitatud faili sisu ekraanile.

 

#include #include #include #include #include #include

LEDide viigud pin led_red = PIN(C, 5); pin led_yellow = PIN(C, 4); pin led_green = PIN(C, 3); Nuppude viigud pin button1 = PIN(C, 0); pin button2 = PIN(C, 1); pin button3 = PIN(C, 2);

int main (void) {

int f_err_flag = -1; //Ketta vea lipp
int d_err_flag = -1; //Failisüsteemi vea lipp
char f_err_buf[16];
char d_err_buf[16];

int variableName = 0;
static FATFS FATFS_Obj;
      FIL fil_obj;
char read_buf[20];
unsigned char new_value1, old_value1 = 0;
unsigned char new_value2, old_value2 = 0;
unsigned char new_value3, old_value3 = 0;
	
// Seab LEDid töökorda
pin_setup_output(led_red);
pin_setup_output(led_yellow);
pin_setup_output(led_green);

Seab nupud töökorda pin_setup_input_with_pullup(button1); pin_setup_input_with_pullup(button2); pin_setup_input_with_pullup(button3); Lülitab LEDid välja

pin_set(led_green);
pin_set(led_yellow);
pin_set(led_red);
// Ekraani seadistamine
lcd_gfx_init();

LCD ekraani puhastamine lcd_gfx_clear(); lcd_gfx_backlight(true); Kursori (nähtamatu) ekraani keskele viimine

lcd_gfx_goto_char_xy(3, 2);

Programmi nime kuvamine lcd_gfx_write_string(„SD Card“); while (1) { Loeb nuppude väärtused.

 		new_value1 = pin_get_debounced_value(button1);
	new_value2 = pin_get_debounced_value(button2);
	new_value3 = pin_get_debounced_value(button3);

Nupp S1 alla vajutatud. Registreeritakse ainult üks vajutus. if[4] { SD kaardi initsialiseerimine. Ebaõnnestumise korral seatakse vealipp.

		d_err_flag = disk_initialize(0);
		// Viide
		sw_delay_ms(2);
		// Failisüsteemi initsialiseerimine. Ebaõnnestumise korral seatakse vealipp.
		f_err_flag = f_mount(0, &FATFS_Obj);
		// Viide
		sw_delay_ms(2);
		
		
	} 
	
    // Nupp S2 vajutatud. Registreeritakse ainult üks vajutus.
	if((!new_value2) && (old_value2))
	{
		// Faili "fail.txt" avamine lugemisreziimis.
		f_open(&fil_obj, "/Homelab/fail.txt", FA_READ);
		// Failist esimese 14 tähemärgi lugemine.
		f_gets (read_buf,14, &fil_obj);
		f_close(&fil_obj);
		// Faili esimese 14 tähemärgi ekraanile kirjutamine.
		lcd_gfx_goto_char_xy(0, 0);
		lcd_gfx_write_string(read_buf);
	}

Nupp S3 vajutatud. Registreeritakse ainult üks vajutus if[5] { Suvaline muutuja, mis salvestatakse faili.

		variableName = 4;			
		// Kettale luuakse kaust "Homelab".
		f_mkdir("Homelab");	
		
		// Loodud kausta tekitatakse tekstifail "fail.txt".
		f_open(&fil_obj, "/Homelab/fail.txt", FA_CREATE_NEW);
		// Fail avatakse kirjutusreziimis.
		f_open(&fil_obj, "/Homelab/fail.txt", FA_WRITE);		
		// Faili kirjutamine.
		f_printf(&fil_obj, "Variable: %d", variableName);

Faili sulgemine f_close(&fil_obj); } Jätab eelmise nupu väärtuse meelde

	old_value1 = new_value1;
	old_value2 = new_value2;
	old_value3 = new_value3;		
	
	// Kui SD-kaart on initsialisseritud ja töökorras, siis põleb roheline LED
	// ja vastupidisel juhul punane LED.
	if((f_err_flag == 0) && (d_err_flag == 0))
	{
		pin_clear(led_green);
		pin_set(led_red);			
	}
	else
	{			
		pin_set(led_green);
		pin_clear(led_red);
	}
	// Ekraanile kuvatakse vealippude olekud. Need on järgnevad:
	// -1 initsialiseerimata
	//  0 viga ei ole
	//  1 (või suurem) viga		
	sprintf(f_err_buf, "Error_f: %02d", f_err_flag );
	sprintf(d_err_buf, "Error_d: %02d", d_err_flag );
	lcd_gfx_goto_char_xy(0, 4);
	lcd_gfx_write_string(f_err_buf);
	lcd_gfx_goto_char_xy(0, 5);
	lcd_gfx_write_string(d_err_buf);
	
	// Viide
	sw_delay_ms(2);		
}

}

/home/www/roboticlab/homelab_data/pages/en/examples/storage/network.txt— MISSING PAGE —

Exercises

Machine vision

CMUCam3 kaamera emuleerimine CMUCam2-ena

Vajalik tarkvara ja kirjandus
Sissejuhatus

CMUCam3 kaamera tarkvara ei toeta lihtsat serial pordi kaudu andmevahetust. Kuna see võimekus oli olemas CMUCam2 kaameral, siis on tehtud ka CMUCam3 jaoks tarkvara, mis emuleerib kaamera eelmist versiooni. Kasutada saab eelmise versiooni CMUcam2GUI liidest ja serial pordi käsklusi.

Kaamera seadistamine

CMUCam3 kaamera eelmise versiooni emuleerimiseks tuleb alla tõmmata ja installeerida lingil 6 toodud flash utiliit ja lingil 5 toodud hex fail. Peale hex faili kaamerasse laadimist emuleeritaksegi seda kui CMUCam2-te ja edaspidi tuleb kasutada eelmise versiooni jaoks mõeldud GUI-i pildi vaatamiseks. Lisaks on CMUCam2 andmelehel olemas serial käsustik kaameraga suhtlemiseks. Pikem ingliskeelne kirjeldus flashimisest on toodud CMUCam3 kasutusjuhendis lingil 1.

CMUCam2 GUI

Tegemist on arvutile mõeldud graafilise kasutajaliidesega, mis võimaldab kaamerast pilti vaadata ja erinevaid muid funktrsioone testida. Kasutajaliidese kohta on õpetus toodud lingil 3 ja tarkvara lingil 4. Olgu kohe öeldud, et see on Java programm ja käivitamiseks tuleb installida endale meelepärane JRE (Java Runtime Environment), mis võimaldab jar tüüpi faili käivitada.

Programmi kasutamiseks tuleb kaamera ühendada võimaluse korral otse arvuti COM pordiga või kasutada selleks USB-Serial üleminekut. Programmi käivitamisel küsitakse COM pordi numbrit, kuhu kaamera on ühendatud. Peale seda avaneb programmi töökeskkond.

Üleval ääres on menüü, kust saab erinevaid funktsioone valida, nagu näiteks servode liigutamine. Kaamera pildi vaatamiseks tuleb minna vahelehele „Camera View“ ja seejärel vajutada „Grab Frame“ nuppu. Nüüd laetakse kaamerast pilt. Seda saab ka salvestada.

Kaamera vaheleht on veel selle poolest väga tähtis, et pildil soovitud värvil klikates saab teada selle koodi. Samal ajal tõstetakse teised sama värvi pikslid kah esile.

Kaamera vaada

Pilt 1. Kaamera GUI aken

Pildil kaks on toodud „Color“ vahekaart, kus saab eespool valitud värvi otsimist testida. Sinna genereeritakse automaatselt värvi minimaalsed ja maksimaalsed väärtused, mida saab soovi korral muuta. Värvi trackimiseks tuleb vajutada „Track Color“ nuppu. Ümber sama värvi alade joonistatakse ristkülik. Kaamera saadab välja selle ristküliku külgede kaks koordinaati ja lisaks ka selle keskpunkti koordinaadid.

Leitud on pall

Pilt 2. Color Tracking

Kodulaboriga värviotsimist tehes on antud programmiga hea värvivahemik määrata, mida otsida ja see reaalselt ära testida. Kodulabori väikesel ekraanil on ainult numbriline info ja selle järgi midagi kindlaks määrata on võimatu.

CMUCam3 kaamera kasutamine kodulaboriga

Antud näited on mõeldud kasutama CMUCam3-kaamerat emuleeritud reziimis. See ei nõua kaamera enda programmeerimist ja saab keskenduda lihtsamata rakenduste arendamisele Kodulabori moodulitega. Suhtlemine käib, kasutades CMUCam2 juhendis toodud käsustikku.

Kodulabori tarkvara

Kodulabori poolne näitekood on tehtud, kasutades nii palju kui võimalik Kodulabori teeki. Siiski serial liidesest andmete lugemine on kiiruse huvides katkestustepõhine. Tarkvara on jagatud eraldi failideks, millest main.c failis paikneb üldine funktsionaalsus, nagu ekraani ja nuppude juhtimine.

Failis CMUCAM.c paiknevad kaameraspetsiifilised funktsioonid. Hetkel on sinna koondatud värvi otsimise ja andmete vastuvõtmiseks vajalik. Kuna erinevaid käskusi on küllaltki palju, siis on seda faili soovitav vastavalt projekti vajadustele täiendada.

Fail USART.c on mõeldud puhtalt serial ühenduse teenindamiseks. Failis on funktsioon ühenduse seadistamiseks ja ka mõlemas suunas andmevahetuseks. Olgu veel öeldud, et kui andmed saabuvad, käivitatakse failis CMUCAM.c paiknev CMUPacketHandler, mis teeb kindlaks ja töötleb saabuva märgi ja koostab neist paketi. CMUPacketHandler on näites mõeldud kindlate pakettide töötlemiseks ja seda võib vajadusel täiendada, lisades uute pakettide tuge jne.

Värvi otsimine

Vajalik riistvara
  1. CMUCam3
  2. Kodulabori Kontrollermoodul ATmega2561
  3. Kodulabori Kommunikatsioonimoodul
  4. Kodulabori Kasutajaliidese moodul
Kirjeldus

Programm seadistab CMU kaamera kindla värvi otsimise reziimi. Kodulabori ekraanil kuvatakse ümber seda värvi ala joonistatud ristküliku keskpunkti koordinadid.

Programm töös

Pilt 3. Programm koordinaate kuvamas

Kasutamine

Ühenda moodulid kokku. Lülita kaamera toitelüliti sisse. Vajutades nupule S2 hakkab kaamera eelseadistatud värvi otsima. Tulemus kuvatakse ekraanil formaadi Mx ja My. Kus Mx ja My on ümber valitud värvi ala joonistatud ristküliku keskpunkti koordinaadid. Kui värvi ei nähta kuvatakse nullid. Programm on seadistatud otsima oranzhi värvi.

Lihtne terminal

Vajalik riistvara
  1. CMUCam3
  2. Kodulabori Kontrollermoodul ATmega2561
  3. Kodulabori Kommunikatsioonimoodul
  4. Kodulabori Kasutajaliidese moodul
Kirjeldus

Programm kuvab suvalisi CMU-CAM pakette kodulabori ekraanile. Lisaks saab nuppude abil kaamerat algväärtustada, värvi otsida ja tarkvara versiooni küsida.

Kasutamine

Ühenda moodulid kokku. Lülita kaamera toitelüliti sisse. Vajutades nupule S1 kuvatakse kaamera tarkvara versioon. Nupp S2 paneb kaamera eelseadistatud värvi otsima. Nupp S3 aga resetib kaamera.

Example projects

Some instructions on how to prepare a project documentation, what themes should be dealt with and what should be written on every theme are brought out in this example project. It is only practical to use a documentation of a typical project as an example. Unfortunately, the documentation of the project is too voluminous due to the graphic material and would not have fit here anyway. Therefore, all the main points are reflected in this example project, but not in its entirety. For example, only one detail is showed from drawings and only one PCB from electronic schemes. Nevertheless, in real documentation all created details should have their drawings and schemes of PCB. Hopefully this example project is helpful for teachers as well, as it is easier for them to explain what they expect from students at the end of the project and how it should be presented. However, few points can be left out from the documentation depending on the level of the student and the actual situation.

Report

In order to engineer a simple mechatronic device it is needed to project the construction and mechanics, electronics and sensors, control system and software for this device. At the end of the project a report should be compiled. It is a documentation which should at least consist following content points:

  • Titlepage
  • Summary
  • Summary (in foreign language)
  • Table of contents
    1. Initial task
    2. System requirements and limitations
    3. The overall system model
      Structure and functionality of a system as block diagrams. In addition, instructions for use case diagram, interface diagram etc. can be composed.
    4. Design solutions
      At least three different conceptual solutions of how to solve the task. Suitable are manually sketched diagrams, sketches etc. Documentation with comments.
    5. Mechanics
      Preferably a 3D model with drawings of essential nodes and engineering instructions. If a node requires special instructions, then assembly drawings and instructions as well. If possible, add an animation on functioning of the system.
    6. Electronics
      Give the overall block diagram, where all the used modules are showed (controller, motor actuator, motor, encoder etc. and their connections). At opportunity provide a standard electronic unit and PCB assembly layout.
    7. Control system
      Control algorithm and source code. If self made functions are used, then provide a table of functions and parameters, table of interruption priorities etc.
    8. Ready-to-use solution
      Description and pictures
    9. Economic calculation
      The list of components with cost, time estimates etc.
    10. Project management
      The project schedule, resource allocation, division of labor, the crew's contribution, the minutes of meetings etc.
    11. Summary and conclusions
      What was difficult, what would you do differently, what you gained from the project etc. In the summary a short description of the work done, problems encountered and a description of the outcome should be outlined. It is also good to add your opinion on the necessity of the project, what it offers to the members of the project and what should be done differently in the future, what was learned and what would be suggested to the supervisors and organizers of the project.
  • References and materials used
  • Annexes

The following example project is a sample of how to compile a documentation and a report on the project. Unfortunately, the report is in an abbreviated form due to the limited volume of this book, but it is aimed to show the different aspects of documentation.

Mobile robot platform

Mobile robot is one of the most popular robot for construction. Very common are sumo robots, sports robots (football, volleyball etc.), robots simulating rescue operations (firefighting, person or object finding etc.) and many other. For these kinds of robots there are many different competitions in the world and in Estonia, even standard classes have been developed (eg sumo robots). The common feature for these types of robots is mobile platform, which may have different construction and capabilities, but its main functionality remains the same. It is controlling the motors and basic navigation, which includes avoiding objects and travelling to the desired destination. Usually, a specific functionality is added to the main functionality, which is planned according to the requirements and opportunities set for the project.

Here we look at the documentation of a typical mobile robot platform project and its different phases.

Initial tasks

Plan and construct a multifunctional mobile robot platform with basic navigation functionality using HomeLab components. Robot platform must have an easy-to-change operational functionality, when equipped with different gadgets:

  • Manipulator
  • Radar
  • Camera

Robot must be able to move on a flat surface in indoors.

Requirements

  • Maximum dimensions: 20 cm x 20 cm x 20 cm
  • Maximum weight 2 kg
  • Speed max. 0,2 m/s
  • Full autonomy

Restrictions

  • Must be constructed mainly from HomeLab components
  • Cannot exceed the cost limit 10 000 EEK

The overall model of the system

The overall model of the system is presented as a block diagram. It describes the structure, behaviour and other important aspects of the system. As an example, an hierarchical model of the overall system is depicted below.

Model of system structure

Design solutions

For this task the team used a brainstorming method and generated 3 conceptually different solutions. Evaluation matrix was compiled and the most optimum construction was found. The main differences of the solutions lay in the movement schemes.

Design solutions

Simplified evaluation matrix was as following:

Function/Solution I II III Weight factor
Cost 3 4 6 0,8
Complexity of building 2 4 7 0,7
Maneuverability 4 8 8 0,5
Permeability 5 8 2 0,3
Applicability of HomeLab 5 4 5 0,9
Weight 5 6 7 0,8
Total (with weight factor) 1927 28

Evaluation scale was 1-10 points and weight factor 0-1. Weight factors were chosen according to the requirements and restrictions set for this system. Eg, although solution 2 was significantly more capable moving on rough ground, it wasn't required in the preliminary task and therefore the weight factor was low.

Based on the assessment the optimum solution for given task was proved to be a platform moving on two wheels with two separate motors. Further work continued developing the chosen solution into a real system.

Mechanics

Mechanics was tried to make as simple as possible, while following the principle of modularity. The front and the rear bumper are identical modules. Electronics have three modules, which are placed on top of each other, allowing simple ribbon cable connections, while ensuring relatively simple changeability of modules. Motors have been selected from HomeLab kit: motors with integrated reducer and coder, which are connected directly to the actuator of the motors. Model aircraft wheels have been used, because they are very light and strong enough for the robot. To simplify the construction the bottom and the top plate are identical. Plates are equipped with holes, allowing different devices to be attached on the top plate. Besides the electronic modules a battery fits between the plates as well.

Primary 3D model of the robot and location of its components.

The bumper of the robot is projected separately and it is integrated with touch sensors and line following sensors. The bumper is made from PCBs and therefore has electricity in addition to construction. Line following sensors are soldered directly to the bumper of the bottom plate. Touch sensors (micro switches) are placed between the bumper plates and are covered by a single rubber piece at front. The rubber piece absorbs the hit and at the same time enables to identify where the hit came from.

Bumper plate drawing

Electronics

The electronics of the system is described as a principle scheme and electronic scheme with PCB assembly scheme.

Block diagram of electronic components

 

As an example, Line following sensors electric scheme and respective PCB assembly scheme of the robot's bumper is shown.

Electric scheme of the bumper sensors
Assembly scheme of the bumper

 

Control system

The control system of the robot derives from behavioral model and is set by the functionality, requirements and restrictions of the initial task. From the behavioral model of the system a specified control program is created, which in turn is the basis for software program code. All three levels (behavioral model-algorithm-source code) must be consistent with each other.

Algorithm

Algorithm describes the control logic of the system and is depicted as a block diagram. A few elements and description of their relations is enough to create a simple algorithm. If the algorithm of the robot is composed correctly, then it is relatively easy to compose a control program for this robot. Mainly two different objects are used in the algorithm: a rectangle with rounded corners, which marks an activity and a small diamond for controlling a condition, followed by a startup of further activities in accordance with the results of the inspection.

Meanings of the symbols used in the algorithm:

SymbolMeaning01-1
M1left motorstoprotates clockwiserotates counter-clockwise
M2right motorstoprotates clockwiserotates counter-clockwise
Ffirst middle touch sensorno signalsignal
FRfirst right touch sensorno signalsignal
FLfirst left touch sensorno signalsignal
dreference
Algorithm state diagram

Source code

Simple navigation

#include #include #include

Defining bumper pins pin front = PIN(C, 0); pin frontleft = PIN(C, 1); pin frontright = PIN(C, 2); Main program int main(void) {

// Initiating motors 0 and 1 
dcmotor_init(0);
dcmotor_init(1);
// Sensor pins as inputs
pin_setup_input_with_pullup(front);
pin_setup_input_with_pullup(frontleft);
pin_setup_input_with_pullup(frontright);
// Endless cycle
while (true)
{
	// Clockwise motor startup 
	dcmotor_drive(0, 1);
	dcmotor_drive(1, 1);
	    
	// Controlling the middle sensor signal
	if (pin_get_value(front))
	{
		// Reversal of the motors
		dcmotor_drive(0, -1);
		dcmotor_drive(1, -1);
		// Paus 1 second
		sw_delay_ms(1000);
		// Left motor clockwise startup  
		dcmotor_drive(0, 1);
		
		// Paus 2 seconds
		sw_delay_ms(2000);
	}
	// Controlling the left sensor signal
	else if (pin_get_value(frontleft))
	{
		// Reversal of right motor
		dcmotor_drive(1, -1);
		
		// Paus 2 seconds
		sw_delay_ms(2000);
	}
	// Controlling the right sensor signal
	else if (pin_get_value(frontright))
	{
		// Reversal of left motor 
		dcmotor_drive(0, -1);
		
		// Paus 2 seconds
		sw_delay_ms(2000);
	}
}

}

Ready-to-use solution

Robot platform completed under this project is largely made from plastic, except from motor mountings, which are made from aluminum. Electronic modules are placed on top of each other and the battery is loose between the plates. Bumpers are made from PCB and painted black. The top plate of the robot is completely flat, allowing to attach different desired devices. A simple radar was installed on the robot, which consisted of a small RC servo motor and an infra red sensor. As a second solution, intelligent camera module was installed on the platform for solving machine vision problems. Both solutions are brought out on the following pictures. Standard manipulator was tested as a third device, which components are controlled with standard servo motors as well, using serial interface for controlling their actuator.

Robot with infrared radar
Robot with intelligent camera module (CMUcam3)

Economic calculation

Economic calculation includes the cost of components and robot production costs. The currency used in following tables is Estonian Kroon (EEK).

Table of components cost

ComponentMarkQuantityPriceCost
MotorM LE149.6.432500.-1000.-
MicrocontrolleruC ATmega1281900.-900.-
Motors actuator boardActuator Board v1.21700.-700.-
Power plateTP1500.-500.-
Line following sensorsLFS QRD1114830.-240.-
Touch sensorsTS Microswitch825.-200.-
Hull plateABS 450.-200.-
PCB blank 250.-100.-
Motor mountings profileAl-L 210.-20.-
Wheel60/10 mm 230.-60.-
BatteryNI-MH 9,6 V1350.-350.-
Different cables 1020.-200.-
Nuts-bolts 150.-50.-
Other acsessories 1100.-100.-
Total 4620.-

Estimated labor and production cost for a single copy.

WorkTime (h)PriceCost
Milling construction details1300.-300.-
Milling PCBs (bumpers)0,5500.-250.-
Construction of the robot0,5250.-125.-
Building bumpers (soldering components)1300.-300.-
Programming5300.-1500.-
Compiling documentation3250.-750.-
Total 11 3225.-

Estimated cost of the robot 7845.-

The cost calculation of the robot is estimated, since it is an educational project, where most of the work and construction is done in significantly larger volumes, but without direct charge. Therefore, the work and the approximate time spent does not reflect the real situation.

Project management

Mechatronic system (Robot) is created as a team work with a firm timetable and budget, thus having most of the significant features of a project. The key activities of the project management were: time planning, team work planning and management, budget monitoring and obtaining supplies, current reporting to the supervisor, presentation and documentation of the outcome. The project report includes working groups minutes of meetings, project plan (preferably in a Gantt diagram), resource allocation (including human resources), planned and actual budget. For example a simple action plan is given as a Gantt diagram.

Action diagram of a project

Summary and conclusions

Economic calculation showed that the production cost of the robot is quite high, especially when dealing with a single original, but remains within a predetermined initial task. Production costs could certainly be substantially reduced through the optimization of materials and components, and producing a larger quantity of robots at the same time. During this project we learned how to project a mechatronic system, how to construct and test it, which gave us the first time experience of this kind.

At the end of the work a fact revealed: in order for the robot to function properly significantly more time should be planned for testing, especially for the software testing. Different modules may not always work properly together, although as a separate experiment it works. This shows that the integration of the modules of the system is a serious challenge, and therefore more time and resources should be planned for this.

In conclusion, we believe that the project was very interesting and instructive, it gave an indication how to design and construct integrated systems.

References and materials used

  1. HomeLab generic manual http://home.roboticlab.eu
  2. ATmega2561 datasheet
  3. Dudziak, R., Köhn, C., Sell, R., Integrated Systems & Design, TUT Press, 2008
  4. Friendenthal, S., Moore, A., Steiner, A., A Practical Guide to SysML, Elsevier, 2008
  5. Perens, A. Project Management, Külim, 1999
  6. Bräunl, T. Embedded Robotics, Springer-Verlag, 2003
[1] x == 5) && (y == 3
[2] weak
[3] (F_CPU / (RFID_BAUDRATE * 16UL
[4] !new_value1) && (old_value1
[5] !new_value3) && (old_value3
et/book.txt · Viimati muutnud: 2018/12/27 12:53 (väline muutmine)
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0