Desde 1994 en la Red. La pagina de los aficionados a la electronica, informatica y otras curiosidades de la vida. No dudes en visitarnos.
Ahora 0 visitas.| 3484499 Visitas (desde Dic. 2011), hoy: 327 Visitas 1000 Pag. Vistas , ultimos 36 dias: 11188 Visitas. 38212 Pag. Vistas. Tu IP: 18.219.25.226
Que ando curioseando:
AutosuficienciaCosas de casaElectronicaEn InternetInformáticaMundo MisticoSin categoríaSociedadTe lo recomiendo

WILL-I tu primer robot con ATMega8

willi[1]

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.

williflow[1]

 

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.

willi3kapcsrajz[1]

 

/* 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

 

Escribe un comentario

Tu comentario