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
Tuitear 2.988 Veces leído 0 comentarios |
9 septiembre 2014 en Electronica | tags: Arduino, Circuitos electrónicos, Electronica |