WILL-I tu primer robot con ATMega8
El robot es controlado con un ATMega8 Atmel que se ejecuta en el oscilador interno a 1MHz. Utiliza 3 microinterruptores y un servo gira sensor de distancia por infrarrojos de Sharp para detectar el medio ambiente. El AVR está programado en AVR-GCC con WinAVR + AVR Studio.
El código es muy simple. El robot espera hasta que se pulse un micro. Que va hacia adelante hasta que se detecta que un objeto delante de ella es menor de aproximadamente 10 cm de distancia (el valor ADC medido es superior a 200). Que mira a la izquierda, midiendo la distancia de cualquier objeto posible, mirando a la derecha y la medición de la distancia de nuevo. Cuando haya terminado con las mediciones, que gira en la dirección donde no hay objeto encontrado. Si uno de los microinterruptores en el extremo de los brazos golpea algo, se genera una interrupción, y el robot invierte durante un tiempo corto, que se convierte en la dirección opuesta.
/* WILL-I V2.0 vezerlo program
Nyomogomb: PD4-es labra kotve
Bal mikrokapcsolo: PD2-es labra kotve (INT0)
Jobb mikrokapcsolo: PD3-es labra kotve (INT1)
Sharp IR szenzor: PC0-as (ADC0) labra kotve
*/
//---------------------------------------------------------------------
#define F_CPU 1000000UL // 1 MHz-es CPU orajel megadasa
#define jobbra 16 // Szervo jobb szelso pozicio
#define kozepre 23 // Szervo kozepso (Neutral) pozicio
#define balra 31 // Szervo bal szelso pozicio
#include <util/delay.h> // idozito, keslelteto rutinokat tart. fajl
#include <avr/io.h> //AVR konstansokat, beallitasokat tart. fájl
#include <avr/interrupt.h> // Megszakitasokat kezelo rutinokat tart. fajl
#include <util/dcmotor.h> // motorvezerlo utasitasokat tart. fajl
volatile int SharpIR = 0;
volatile int SharpIRjobb = 0;
volatile int SharpIRbal = 0;
volatile int Balkapcs = 0;
volatile int Jobbkapcs = 0;
void Konfig10bitADC() // ADC konfiguralas (beallitas)
{
ADMUX |= (1<<REFS0); // Vcc mint referencia
ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0); // ADC engedelyezese, ADC eloosztas = 8 (125 KHz)
}
unsigned int Beolvas10bitADC(unsigned char csatorna)
{
ADMUX = (ADMUX & 0b11110000) | csatorna;
ADCSRA |= (1<<ADSC); // elso ADC konverzio elinditasa
while (ADCSRA & (1<<ADSC)); // varas az atalakitasra
ADCSRA |= (1<<ADSC); // masodik ADC konverzió elindítás
while (ADCSRA & (1<<ADSC)); // varas az atalakitasra
return (ADCL | (ADCH<<8)); // ADC ertek kiolvasasa
}
void KonfigSzervo() // Szervo konfiguralas (beallitas)
{
DDRB = _BV(DDB3); // PORTB 3. lab kimenet (Szervo PWM)
TCCR2 = _BV(WGM20) // Timer2 8bites gyors PWM mod
| _BV(WGM21) // Timer2 8bites gyors PWM mod
| _BV(COM21) // nem-invertalt PWM
| _BV(CS22); // Timer2 eloosztas: 1/64 (61 Hz-es PWM impulzus frekvencia)
OCR2 = 23; // 1.5ms-os kezdeti PWM impulzus (Szervo kozepso (Neutral) pozicio)
}
void Szervo(unsigned char pozicio) // Szervo pozicionalo utasitas
{
OCR2 = pozicio;
}
ISR (INT0_vect) // INT0 megszakitas kiszolgalo rutin utasitasai (Bal mikrokapcsolo)
{
GICR &= ~(1<<INT0); // INT0 letiltasa (nyomogomb perges megakadalyozasa erdekeben)
motor_stop(mind); // Robot STOP!
Balkapcs = 1; //
}
ISR (INT1_vect) // INT1 megszakitas kiszolgalo rutin utasitasai (Jobb mikrokapcsolo)
{
GICR &= ~(1<<INT1); // INT1 letiltasa (nyomogomb perges megakadalyozasa erdekeben)
motor_stop(mind); //Robot STOP!
Jobbkapcs = 1; //
}
int main (void)
{
// portok beallitasa
PORTD |= (1<<PD4); // PD4-es lab bemenet, pull-up bekapcs (nyomogomb)
DDRC &= ~(1<<PC0); // PC0-as lab bemenet (Sharp IR szenzor)
PORTC = 0x00; // PORTC osszes laban a felhuzoellenallasok kikapcsolva
PORTD &= ~(1<<PD2); // PD2 bemenet
PORTD |= (1<<PD2); // PD2-hoz tartozo felhuzoellenallas be
PORTD &= ~(1<<PD3); // PD3 bemenet
PORTD |= (1<<PD3); // PD3-hoz tartozo felhuzoellenallas be
// az INT0 kulso interrupt beallitasa
GICR |= (1<<INT0); // INT0 engedelyezese (PD2-es lab)
MCUCR |= (1<<ISC01); // a lab lefuto elre adjon megszakítást
// az INT1 kulso interrupt beallitasa
GICR |= (1<<INT1); // INT0 engedelyezese (PD2-es lab)
MCUCR |= (1<<ISC11); // a lab lefuto elre adjon megszakítást
sei(); // megszakítások bekapcsolasa
KonfigSzervo(); // Szervo beallitas lefuttatasa
Konfig10bitADC(); // ADC beallitas lefuttatasa
while (PIND & (1<<PD4)); // varakozo cilkus amig PD4 erteke nem 0 (amig a gomb nincs lenyomva)
while (1)
{
// Ha INT0 megszakitas ki van kapcsolva, akkor egy kis varakozas utan bekapcsoljuk
if((GICR & (1<<INT0)) == 0)
{
// varakozas nehany szaz ms-ig, amig a nyomogomb befejezi a pergest
_delay_ms(250);
// minden tovabbi varakozo megszakitas torlese, majd a megszakitasok engedelyezese
GIFR |= (1<<INTF0); // INT0-hoz tartozo jelzobit torlese
GICR |= (1<<INT0); // INT0 megszakítás engedelyezese
}
// Ha INT1 megszakitas ki van kapcsolva, akkor egy kis varakozas utan bekapcsoljuk
if((GICR & (1<<INT1)) == 0)
{
// varakozas nehany szaz ms-ig, amig a nyomogomb befejezi a pergest
_delay_ms(250);
// minden tovabbi varakozo megszakitas torlese, majd a megszakitasok engedelyezese
GIFR |= (1<<INTF1); // INT1-hoz tartozo jelzobit torlese
GICR |= (1<<INT1); // INT1 megszakitas engedelyezese
}
if ( Balkapcs == 1 ) // Ha Bal oldali utkozes tortent, akkor
{
Balkapcs = 0; // Bal oldali utkozest jelzo valtozo torlese
hatra(100); // hatramenet
_delay_ms(1000); // 1.0 s kesleltetes
fordul_jobb(100); // fordulas jobbra
_delay_ms(500); // 0.5 s kesleltetes
}
if ( Jobbkapcs == 1 ) // Ha Jobb oldali utkozes tortent, akkor
{
Jobbkapcs = 0; // Jobb oldali utkozest jelzo valtozo torlese
hatra(100); // hatramenet
_delay_ms(1000); // 1.0 s kesleltetes
fordul_bal(100); // fordulas balra
_delay_ms(500); // 0.5 s kesleltetes
}
elore(100); // teljes gozzel elore!
SharpIR = Beolvas10bitADC(0);
if ( SharpIR > 200 )
{
motor_stop(mind);
Szervo(balra);
_delay_ms(500); // 0.5 s kesleltetes
SharpIRbal = Beolvas10bitADC(0);
_delay_ms(500); // 0.5 s kesleltetes
Szervo(jobbra);
_delay_ms(500); // 0.5 s kesleltetes
SharpIRjobb = Beolvas10bitADC(0);
_delay_ms(500); // 0.5 s kesleltetes
Szervo(kozepre);
if ( SharpIRbal > SharpIRjobb)
{
fordul_jobb(100); // fordulas balra 0.5 s
_delay_ms(500);
}
else
{
fordul_bal(100); //fordulas jobbra 0.5 s
_delay_ms(500);
}
}
else
{
_delay_ms(100); // 0.1 s kesleltetes
}
}
}
Libreria dcmotor.h
/* ATmega8 mikrovezerlo labkiosztas
+--------------+
RESET -|1 PC5 28|-
-|2 PD0 PC4 27|-
-|3 PD1 PC3 26|-
Nyomogomb -|4 PD2 PC2 25|-
Mikrokapcs. jobb -|5 PD3 PC1 24|-
Mikrokapcs. bal -|6 PD4 PC0 23|-
VCC -|7 22 |- GND
GND -|8 21 |- AREF
(xtal) -|9 PB6 20|- AVCC
(xtal) -|10 PB7 PB5 19|- ISP(SCK)
Motor2 A -|11 PD5 PB4 18|- ISP(MISO)
Motor2 B -|12 PD6 PB3 17|- ISP(MOSI), servo PWM
Motor1 A -|13 PD7 PB2 16|- Motor2 PWM
Motor1 B -|14 PB0 PB1 15|- Motor1 PWM
+--------------+
L293D motorvezerlo IC labkiosztas
+---------------+
Motor1 PWM -| 1 1-2EN 5V 16|- VCC
Motor1 A -| 2 BE1 BE4 15|- Motor2 B
Motor1(+) -| 3 KI1 KI4 14|- Motor2(-)
GND -| 4 GND GND 13|- GND
GND -| 5 GND GND 12|- GND
Motor1(-) -| 6 KI2 KI3 11|- Motor2(+)
Motor1 B -| 7 BE2 BE3 10|- Motor2 A
Motor Fesz.(6V) -| 8 VMo 3-4EN 9|- Motor2 PWM
+---------------+
*/
//---------------------------------------------------------------------
#include <avr/io.h>
#define mind 3 // mindket motor
#define Motor1A PD7 // Motor1A = PD7
#define Motor1B PB0 // Motor1B = PB0
#define Motor2A PD5 // Motor2A = PD5
#define Motor2B PD6 // Motor2B = PD6
unsigned char _duty1=0,_duty2=0; /* motor 1 es 2 sebesseget (PWM kitolsesi tenyezot) allito valtozo */
char pwm_ini=0;
char be_b(char _bit) // be_b(x) fuggveny definialasa PORTB-re
{
DDRB &= ~(1<<_bit); // PORTB x. lab bemenet
return ((PINB & _BV(_bit))>>_bit); /* PORTB x. lab ertekenek beolvasasa (0 vagy 1)*/
}
char be_c(char _bit) // ugyan az mint az elozo fuggveny, de PORTC-re
{
DDRC &= ~(1<<_bit);
return ((PINC & _BV(_bit))>>_bit);
}
char be_d(char _bit) // be_d(x) fuggveny definialasa PORTD-re
{
DDRD &= ~(1<<_bit); // PORTB x. lab bemenet
return ((PIND & _BV(_bit))>>_bit);
}
void ki_b(char _bit,char _dat) /* ki_b(x,y) fuggveny definialasa PORTB-re. PORTB x. labara 0V-ot vagy 5V-ot adunk, attol fuggoen hogy y erteke 0 vagy 1 */
{
DDRB |= _BV(_bit); // PORTB x. lab kimenet
if(_dat)
PORTB |= _BV(_bit); // ha y=1, az x. labra 5V-ot ad
else
PORTB &= ~_BV(_bit); // ha y=0, az x. labra 5V-ot ad
}
void ki_c(char _bit,char _dat) /* ki_c(x,y) fuggveny definialasa PORTC-re */
{
DDRC |= _BV(_bit);
if(_dat)
PORTC |= _BV(_bit);
else
PORTC &= ~_BV(_bit);
}
void ki_d(char _bit,char _dat) /* ki_d(x,y) fuggveny definialasa PORTD-re */
{
DDRD |= _BV(_bit);
if(_dat)
PORTD |= _BV(_bit);
else
PORTD &= ~_BV(_bit);
}
void pwm_init() //Timer1 PWM beallitasa
{
TCCR1A |= (1<<WGM10); //8 bites fazishelyes PWM
TCCR1B |= (1<<CS10); //elooszto = FCPU/1
}
void pwm(char _channel,unsigned int _duty) /* pwm(a,b) fuggveny definialasa. a = 1 vagy 2 attol fuggoen hogy melyik motor, b = 0 – 100% (PWM kitoltesi tenyezo) */
{
_duty = (_duty*255)/100; /*motor sebesseg konvertalasa 0-100%-rol 0-255-re */
if(pwm_ini==0)
{
pwm_init();
pwm_ini=1;
}
if(_channel==1)
{
TCCR1A |= _BV(COM1A1); //nem-invertalt PWM, A csatorna
DDRB |= _BV(PB1); // PORTB PB1 lab kimenet
OCR1A = _duty; // motor1 pwm kitoltesi tenyezo
_duty1 = _duty;
}
else if(_channel==2)
{
TCCR1A |= _BV(COM1B1); //nem-invertalt PWM, B csatorna
DDRB |= _BV(PB2); // PORTB PB2 lab kimenet
OCR1B = _duty; // motor2 pwm kitoltesi tenyezo
_duty2 = _duty;
}
else if(_channel==3)
{
TCCR1A |= _BV(COM1A1); //nem-invertalt PWM, A csatorna
DDRB |= _BV(PB1);
OCR1A = _duty;
_duty1 = _duty;
TCCR1A |= _BV(COM1B1); //nem-invertalt PWM, B csatorna
DDRB |= _BV(PB2);
OCR1B = _duty;
_duty2 = _duty;
}
}
void motor(char _channel,int _power) /* motor(a,b) fuggveny definialasa. a = 1 vagy 2 attol fuggoen hogy melyik motor, b = -100% – 100% (motor sebesseg) */
{
if(_power>0) // ha b (motor sebesseg) > 0, motor elore
{
pwm(_channel,_power); // motor PWM bekapcsol
if(_channel==1) // ha a=1 (motor1 elore)
{
ki_d(Motor1A,1);
ki_b(Motor1B,0);
}
else if(_channel==2) // ha a=2 (motor2 elore)
{
ki_d(Motor2A,0);
ki_d(Motor2B,1);
}
}
else // ha b (motor sebesseg) < 0, motor hatra
{
pwm(_channel,abs(_power)); // motor PWM bekapcsol
if(_channel==1) // ha a=1 (motor1 hatra)
{
ki_d(Motor1A,0);
ki_b(Motor1B,1);
}
else if(_channel==2) // ha a=2 (motor2 hatra)
{
ki_d(Motor2A,1);
ki_d(Motor2B,0);
}
}
}
void motor_stop(char _channel) /* motor_stop(a) fuggveny definialasa. a = 1, 2 vagy mind (3) attol fuggoen hogy melyik motort akarjuk megallitani */
{
pwm(_channel,0); // motor PWM kikapcsol
if(_channel==1 ||_channel==3) //motor1 stop
{
ki_d(Motor1A,0);
ki_b(Motor1B,0);
}
if(_channel==2 ||_channel==3) //motor2 stop
{
ki_d(Motor2A,0);
ki_d(Motor2B,0);
}
}
void motor_ki()
{
pwm(3,0); // motor PWM kikapcsol, motor1 es 2 stop
ki_d(Motor1A,0);
ki_b(Motor1B,0);
ki_d(Motor2A,0);
ki_d(Motor2B,0);
}
void elore(int speed) /* elore(z) fuggveny definialasa, mindket motor elore, z = 0-100% */
{
motor(1,speed);
motor(2,speed);
}
void hatra(int speed) /* hatra(y) fuggveny definialasa, mindket motor hatra, y = 0-100% */
{
motor(1,speed*-1);
motor(2,speed*-1);
}
void fordul_bal(int speed) /* fordul_bal(n) fuggveny definialasa, balra fordulas: motor1 elore, motor2 hatra, n = 0-100% */
{
motor(1,speed);
motor(2,speed*-1);
}
void fordul_jobb(int speed) /* fordul_jobb(m) fuggveny definialasa, jobbra fordulas: motor1 hatra, motor2 elore, m = 0-100% */
{
motor(1,speed*-1);
motor(2,speed);
}
Fuente: http://letsmakerobots.com/robot/project/will-i
|
|
![]() | 9 septiembre 2014 en Electronica | tags: Arduino, Circuitos electrónicos, Electronica |









![willi[1]](http://www.pesadillo.com/pesadillo/wp-content/uploads/2014/07/willi1.jpg)
![williflow[1]](http://www.pesadillo.com/pesadillo/wp-content/uploads/2014/07/williflow1.jpg)
![willi3kapcsrajz[1]](http://www.pesadillo.com/pesadillo/wp-content/uploads/2014/07/willi3kapcsrajz1.jpg)











