• No se han encontrado resultados

DDRA = 0xFF; // Configure port B as output while(1)

{

//TODO:: Please write your application code

PORTA = 0b00110000; // Display Number 1 _delay_ms(1000); // Wait for 1s

PORTA = 0b01011011; // Display Number 2 _delay_ms(1000); // Wait for 1s

PORTA = 0b01001111; // Display Number 3 _delay_ms(1000); // Wait for 1s

PORTA = 0b01100110; // Display Number 4 _delay_ms(1000); // Wait for 1s

PORTA = 0b01110111; // Display Letter A  _delay_ms(1000); // Wait for 1s

PORTA = 0b00111001; // Display Letter C  _delay_ms(1000); // Wait for 1s

PORTA = 0b01111001; // Display Letter E  _delay_ms(1000); // Wait for 1s

PORTA = 0b01110001; // Display Letter F  _delay_ms(1000); // Wait for 1s computers, televisions, instrument panels, and other devices ranging from aircraft cockpit displays, to every-day consumer devices such as video players, gaming devices, clocks, watches, calculators, and telephones. Among its major features are its

lightweight construction, its portability, and its ability to be produced in much larger screen sizes than are practical for the construction of cathode ray tube (CRT) display technology. Its low electrical power consumption enables it to be used in  battery- powered electronic equipment. It is an electronically-modulated optical device made up of any number of pixels filled with liquid crystals and arrayed in front of a light source (backlight) or  reflector to produce images in color or monochrome. The earliest discoveries leading to the development of LCD technology date from 1888. By 2008, worldwide sales of televisions with LCD screens had surpassed the sale of CRT units.

Fig3.1.2 Liquid crystal display (LCD)

The most commonly used LCDs found in the market today are 1 line,2 lines or 4 lines LCDs which have only one controller and support at most 80 characters , whereas LCDs supporting more than 80 characters make use of 2 HD44780 controllers. Most LCDs with 1 controller has 14 pins and LCDs with 2 controllers have 16 pins.

LCD pin descriptions:

The LCD discussed in this section has 14 pins. The function of each pin is given in table.

Figure3.1.3 Pin description

1) Vcc & VEE: While Vcc provide +5V and ground, respectively, VEE is used for controlling LCD contrast.

2) RS –  register select: There are two very important registers inside the LCD.

The RS pin is used for their selection as follows:

If RS = 0, the instruction command code register is selected, allowing the user to send a command such as clear display, cursor at home, etc.

If RS = 1 the data register is selected, allowing the user to send data to be displayed on the LCD.

3) R/W input allows the user to write information to the LCD or read information from it. R/W = 1 when reading; R/W =0 when writing.

4) E –  Enable: The enable pin is used by the LCD to latch information presented to its data pins. When data is supplied to data pins, a high to low pulse must  be applied to this pin in order for the LCD to latch in the data present at the

data pins. This pulse must be a minimum of 450 ns wide.

5) D0 –  D7: The 8 bit data pins, D0 –  D7, are used to send information to the LCD or read the contents of the LCD’s internal registers.  To display letters and numbers, we send ASCII codes for the letters A –  Z, a –  z, and numbers 0  –  9 to these pins while making RS = 1.There are also instructions command codes that can be sent to the LCD to clear the display or force the cursor to the home position or blink the cursor.

We also use RS = 0 to check the busy flag bit to see if the LCD is ready to receive information. The busy flag is D7 and can be read when R/W =1 and RS = 0, as follows: if R/W =1, RS =0. When D7 = 1(busy flag = 1), the LCD busy taking care of internal operations and will not accept any new information. When D7 = 0, the LCD is ready to receive new information. Note: It is recommended to check the busy flag  before writing any data to the LCD.

Data display: In LCD, one can put data at any location. The following shows address locations and how they are accessed:

RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0

0 0 1 A A A A A A A

LCD addressing

DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0

Line 1(max.) 1 0 0 0 0 0 0 0

Line 1(min.) 1 0 1 0 0 1 1 1

Line 2(max.) 1 1 0 0 0 0 0 0

Line 2(min.) 1 1 1 0 0 1 1 1

The upper address range can go as high as 0100111 for 40 character-wide LCD while for the 20 character-wide LCD it goes up to 010011 (19 decimal = 10011  binary). Notice that the upper range 0100111 (binary) = 39 decimal which

corresponds to locations 0 to 39 for the LCDs of 40*2 size.

Program:

#include "mega32.h"

#define rs 2 // defined portc.3 as register select pin

#define en 3 // defined portc.2 as enable pin  void delay(unsigned int ms);

 void delay(unsigned int ms) // small delay function {

unsigned int i,j;

for(i=0;i<=ms;i++) for(j=0;j<=5;j++);

}

 void msdelay(unsigned int ms) // medium delay function {

unsigned int i,j;

for(i=0;i<=ms;i++) for(j=0;j<=122;j++);

}

 void lcd_cmd(unsigned char cmd) // command function {

 void lcd_char(unsigned char data) //character Display function {

delay(1);

PORTC &= (~(1<<en));

msdelay(5);

temp = data;

temp <<= 4;

PORTC&=0x0F;

PORTC |= temp;

PORTC |= (1<<rs);

PORTC |= (1<<en);

delay(1);

PORTC &= (~(1<<en));

msdelay(5);

}

 void lcd_string(unsigned char *dat) // string Display function {

 while(*dat != „\0′) {

lcd_char(*dat++);

} }

 void lcd_init() // LCD initializing function {

lcd_cmd(0×33);

lcd_cmd(0×32);

lcd_cmd(0×28); //4 datalines,2line display(system set) lcd_cmd(0x0C); //Dislay on,cursor off

lcd_cmd(0×01); //Clear lcd }

3.7 Interfacing of STEPPER MOTOR With AVR

Stepper motors pairs nicely with a smart device like a microcontroller to create precise digitally controlled movements that has made possible many of modern gizmos around us. For example a printer, scanner ,plotters, fax, floppy drive (not so modern though!), automatic industrial machines like CNC (Computer numerically controlled) drills, laser shows etc. Though to a naked eye the motor of stepper look no other than a DC motor but the difference is that each step of a stepper motor is in control. For example a high speed desktop printer when the paper moves forward, to a novice it seems like a motor is just  pushing the paper out but in reality the control board inside the printer request the motor

to move the paper exactly same amount that has been printed. This precise movement keeps the next printed pixel in alignment with previously printed pixels.

The thing is that the stepper motors have certain amount of steps per full 360 degree rotation (exact number depends on model) the controller can request the stepper to rotate any number of steps. For example if you are making a robot, you want it to move exactly as per your program. Like if you say go forward 100cm then rotate right 45 degrees and move forward 50 cm. You cannot do this with DC Motors, because for it you need to calculate the exact speed for DC motor and then use blind timing for movement. Say if you happen to find out the your robot moves at 5cm per second then to move 100cm it will require 20 second. So you keep the motor on for 20 second and expect that it has moved 100cm. But this can prove failure if the speed of robot changes due to drop in level of battery or some additional weight or simply due to an uneven terrain etc. So this method is not so trustworthy. epper motors pairs nicely with a smart device like a

microcontroller to create precise digitally controlled movements that has made possible many of modern gizmos around us. For example a printer, scanner ,plotters, fax, floppy drive (not so modern though!), automatic industrial machines like CNC (Computer numerically controlled) drills, laser shows etc. Though to a naked eye the motor of stepper look no other than a DC motor but the difference is that each step of a stepper motor is in control. For example a high speed desktop printer when the paper moves forward, to a novice it seems like a motor is just pushing the paper out but in reality the control board inside the printer request the motor to move the paper exactly same amount that has been printed. This precise movement keeps the next printed pixel in alignment with previously printed pixels.

The thing is that the stepper motors have certain amount of steps per full 360 degree rotation (exact number depends on model) the controller can request the stepper to rotate any number of steps. For example if you are making a robot, you want it to move exactly as per your program. Like if you say go forward 100cm then rotate right 45 degrees and move forward 50 cm. You cannot do this with DC Motors, because for it you need to

calculate the exact speed for DC motor and then use blind timing for movement. Say if you happen to find out the your robot moves at 5cm per second then to move 100cm it will require 20 second. So you keep the motor on for 20 second and expect that it has moved 100cm. But this can prove failure if the speed of robot changes due to drop in level of battery or some additional weight or simply due to an uneven terrain etc. So this method is not so trustworthy.

Stepper motors pairs nicely with a smart device like a microcontroller to create precise digitally controlled movements that has made possible many of modern gizmos around us. For example a printer, scanner ,plotters, fax, floppy drive (not so modern though!), automatic industrial machines like CNC (Computer numerically controlled) drills, laser shows etc. Though to a naked eye the motor of stepper look no other than a DC motor but the difference is that each step of a stepper motor is in control. For example a high speed desktop printer when the paper moves forward, to a novice it seems like a motor is just  pushing the paper out but in reality the control board inside the printer request the motor

to move the paper exactly same amount that has been printed. This precise movement keeps the next printed pixel in alignment with previously printed pixels.

The thing is that the stepper motors have certain amount of steps per full 360 degree rotation (exact number depends on model) the controller can request the stepper to rotate any number of steps. For example if you are making a robot, you want it to move exactly as per your program. Like if you say go forward 100cm then rotate right 45 degrees and move forward 50 cm. You cannot do this with DC Motors, because for it you need to calculate the exact speed for DC motor and then use blind timing for movement. Say if you happen to find out the your robot moves at 5cm per second then to move 100cm it will require 20 second. So you keep the motor on for 20 second and expect that it has moved 100cm. But this can prove failure if the speed of robot changes due to drop in level of battery or some additional weight or simply due to an uneven terrain etc. So this method is not so trustworthy.

The second method is the use of stepper motors. Say you have a stepper motor of 7.5 degree per step (that means it move 7.5 degree for single step or their are 48 step in full rotation) and their is a gear reduction of ratio of 1:75 then you can control the stepper with an accuracy of 0.1 degree per steps! wow! that's really precise! Now if we assume you have attached a wheel of radius 3.5 cm then you can control the liner motor of your robot with an accuracy of 0.00611 cm (I leave the math on you). That's pretty decent. To move the motor forward 100cm, you just need to step the motor 100/0.00611 times that is 16,366 times. Instead if you step it 16,202 times it will move 99cm. So now the bot is  pretty much in your control.

In the same way PCBs are drilled at accurate position, SMT components placed automatically at their desired location, pixel on a paper are printed. Below are some videos that may help you get the point.

Types of stepper motor

Their are many types of stepper motors available but the two most common types are

Unipolar Stepper Motor- Has simple driver requirement. Less torque at same size and weight as compared to bipolar type.

Bipolar Stepper Motor - Has slightly complicated driver requirement. More torque at same size and weight as compared to unipolar type.

Since the Unipolar type is simpler to drive we will start our journe y with it.

Driving Stepper Motor with AVR MCU

In the figure below is shown a simplified construction of a stepper motor. The center is a  permanent magnet(PM) rotor. Around it are four electromagnets. One end of all four

electromagnet is connected to a point called "common". The common is usually

connected to the stepper supply voltage (eg. 12v). The four coils are named A,B,C and D.

To rotate a stepper motor, coils are excited in turns like A,B,C,D. The rotor will try to align itself with the currently exited coil. Lets say that the white point shown on rotor is magnetic north pole. Also assume that when coils are excited, their inner end becomes magnetic south. So the white point on rotor will try to align with the currently excited coil.(As the opposite poles attract)

So to drive a stepper motor from AVR MCU you just need to excite the coils A,B,C,D in turns to rotate the motor in anti clock wire direction. If you want to rotate the motor in clock wise direction simply excite the coil in reverse order that is D,C,B,A.

As the port of AVR can only sink or source 20mA current approximately, they cannot be used to drive the the coils directly. So we need some thing that can boost this current. The  part that fit perfectly in this scenario is ULN2003A. It is a high voltage, high current

Darlington array. It can be driven directly with a TTL level input and the output can source up to 500ma. Since it is array of seven darlington pair, (of which we require only four) it is much compact.

Program

#include <avr/io.h>

#include <util/delay.h>

#include "xstepper.h"

void main() {

 //Initialize the stepper library StepperInit();

_delay_loop_2(10000);

while(1) {

for(uint16_t i=0;i<24*85;i++) {

StepperStepCW();  //Step Clock wise _delay_loop_2(10000);

}

for(uint16_t i=0;i<24*85;i++) {

StepperStepCCW();  //Step Counter Clock wise _delay_loop_2(10000);

} } }

The sample code first runs the stepper full 360 degree in clock wise direction and then full 360 degree in counter clock wise direction. This process is repeated as long as the  board is powered. The code can be compiled using WinAVR Compiler using the AVR

Studio as front end.

ADC Interfacing of AVR (ATmega32)

The Analogue to Digital Converter of the Atmel AVR Microcontroller was one of the main reasons of me choosing it over the cheap AT89S52 microcontroller.

As mentioned in my previous blog post, I had recently given a workshop at the AIUB along with my friend Omee. Due to time shortage, I could not finish my presentation on ADCs. I wanted to share some of the materials that I studied here in my blog post.

In short the ADC converts the voltage level measured at a ADC channel pin to a

corresponding binary value. The converted value is stored in a 16 bit register ADC which is divided into two segments: ADCH and ADCL.

Firstly, the ADC of the ATmega32, or most AVR microcontrollers is 10 bit. That means there are 2^10 or 1024 levels detectable by this ADC which are uniformly spaced over the region of the maximum and minimum voltage level. The minimum voltage is 0V, and maximum is either Vcc or internally generated 2.56V.

Before using the ADC it must be preconfigured. The ADC has 8 channels, that can be selected from the ADMUX register. This is the structure of the ADMUX register:

The ADMUX register also has a ADLAR bit, which can Left Adjust or right adjust the output of the ADC. This shows the effect of changing ADLAR bit value in ADC:

So depending on operation, if the least significant bits can be discarded, and not much accuracy is needed, ADLAR=1 can be used and ADCH value can just be taken readily.

Also the reference voltage of ADC is selected b y the REFS1 and REFS0 bits. It can be used to select an externally generated Vref, as well as the 2.56V internally generated voltage.

For some other control of the ADCs, there are some extra registers: ADC Control and Status Register. Funny thing is, the register structure is different in ATmega8 and

ATmega32, so while this post highlights only ATmega32 microcontroller, it is suggested that you should always consult datasheet before writing your code for a specific

microcontroller.

The ADC can be configured to fire up automatically, so that it converts the value and at the end of conversion, generates an interrupt. These settings are also in the control and status register

ADATE - ADC Auto Trigger Enable, if set it will automatically do the conversion based on the triggering condition (discussed later)

ADIF - ADC Interrupt Flag

ADIE - ADC Interrupt Enable - Triggers Interrupt on completed conversion, works when global interrupt is enabled.

ADPS2-0 - these select the clock frequency of the trigger after which the ADC is triggered.

SFIOR Register (Also termed as ADCSRB in some microcontrollers) has the function of setting the condition on which the ADC is triggered. For free running mode, it always trigger at the specified clock cycle. For other modes, it can be configured to be triggered at a particular hardware condition or timer or counter condition.

It is easy to avoid the division in ADC by using the internal 2.56 V. By using this value we can calculate that

ADC = Vin * 400. So Vin = ADC / 400.

To further illustrate the example, the voltage from a temperature sensor LM35 is sensed with the ADC. The LM35 gives a voltage of 10mV per degree celsius. So the voltage output = 0.01 V * temperature.

So if we measure the value of the ADC, we know that Vin = ADC/400, and again Vin = 0.01 * Temp

So 0.01 * Temp = ADC/400, or Temp = ADC / 400 / 0.01 = ADC / 4

So the temperature is just the measured value of the ADC divided by 4. Since division by 4 can be accomplished by a right shift of 2 binary digits, it can be done quite

computationally efficiently.

This is the model of LM35 IC in proteus. The Temperature is set in the model with the up and down arrows.

Program

#include <avr/io.h>

#include <util/delay.h>

#include <avr/interrupt.h>

/* Code for single pin addressing */

typedef struct {

unsigned char bit0:1;

unsigned char bit1:1;

unsigned char bit2:1;

unsigned char bit3:1;

unsigned char bit4:1;

unsigned char bit5:1;

unsigned char bit6:1;

unsigned char bit7:1;

}io_reg;

#define D0 ((volatile

io_reg*)_SFR_MEM_ADDR(PORTA))->bit4

#define D1 ((volatile

io_reg*)_SFR_MEM_ADDR(PORTA))->bit5

/* Code for 7 seg display */

static unsigned char SEVEN_SEG[] = { 0x3F,

0x06, 0x5B,

0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71};

volatile int temperature;

volatile char garbage;

ISR(ADC_vect) {

temperature = ADCL>>2; /*collect sample from ADC */

garbage = ADCL;

garbage= ADCH;

}

int main (void) {

int delay = 1000;

int i=0;

DDRB = 0xFF;

DDRA |= 0b11110000;

DDRD &= 0x00;

DDRC = 0xFF;

PORTC = 0x00;

//DDRD = 0x00;

/* adc initialization */

ADCSRA |= (1 << ADPS1) | (1 << ADPS0);

ADMUX |= (1 << REFS1) | (1 << REFS0);

//Set ADC to free run mode

SFIOR &= ~((1 << ADTS2) | (1 << ADTS1) | (1 << ADTS0));

// Enables ADC for use ADCSRA |= (1 << ADEN);

// Enable ADC Interrupt ADCSRA |= (1 << ADIE);

// ADC Auto Trigger Enable ADCSRA |= (1 << ADATE);

// Enable Global Interrupts sei();

// Starts ADC conversion ADCSRA |= (1 << ADSC);

while (1) {

//show number in decimal

D0 = 0;

D1 = 0;

PORTB = SEVEN_SEG[temperature/10];

D0 = 0;

D1 = 1;

while (++i < delay);

D0 = 0;

D1 = 0;

PORTB = SEVEN_SEG[temperature%10];

D0 = 1;

D1 = 0;

while (--i > 0);

} }

Chapter 4

REFERANCES

Documento similar