Elektronik / Mikrodenetleyici Projeleri/

Mini Sumo Robot L293D PIC16F877

Sponsorlu Bağlantılar

Mini sumo robotun tasarımı oldukca şık robot devresinde kullanılan mikrodenetleyici pic16f877 motor sürücü için l293d kullanılmş yazılım C dili ile hazırlanmış. Mini densede çok detaylı tüm kaynakları ile paylaşılan bir Sumo robot projesi ayrıca robot yarışmasında büyük rakiplerini pist dışına atıyor :)

SUMO-ROBOT-ÖZELLİKLERİ
Boyutlar 9.9cm(W) x 9.9cm(L) x 6.8cm(H)
Ağırlık 498 gr
MCU PIC16F877-20/SP with 16 MHZ Crystal
8K ROM 368 Byte RAM
Programlama
Language
C
Motor 2 Lego 350 RPM 9 volt dişli motoru
Motor sürücü
chip
L293D
Hız kontrol Yazılımsal PRM (Pulse Rate Modulaton) EMF geri besleme
Lastikler 2 adet 30.4 mm Lego Lastik
Tekerlekler Özel çelikten yapılmış
Sürücü sistemi Lego motor ve şaft
Hız 36 cm/sec
Kuvveti 450 grams (wheels spinning)
Güç kaynağı 2 adet 9 volt alkalin pil
Motor akımı 60mA crusing, 400 mA pushing
Sensörler Kenar tespiti için iki yansıtıcı kızılötesi sensör
iki kanal aktif IR
Telemetri Dış verici için bağlantı
Linx TXM-418-RM (9600 baud 418 MHZ)

control.c yazılım içeriği;

/* Delta Force mini-sumo robot Control program   Sept. 15 2001
   by Dale Heatherington.
   http://www.wa4dsy.net/robot/deltaforce/index.html

   This code is a modified version of the ROBOR
   mini sumo robot control program.  Some functions
   and variables may not be used.

 This program is compiled using the Linux shareware C2C compiler 
 available at: http://www.geocities.com/SiliconValley/Network/3656/
 
 The output .asm code is assembled with the Linux freeware assembler
 gpasm avaiable at:  http://gpasm.sourceforge.net 
 
         
          
----------------------------------------------------------- 

This program is free software; you can redistribute it and/or modify  
it under the terms of the GNU General Public License as published by      
the Free Software Foundation; either version 2 of the License, or         
(at your option) any later version.                                       
                                                                          
This program is distributed in the hope that it will be useful,       
but WITHOUT ANY WARRANTY; without even the implied warranty of            
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             
GNU General Public License for more details.                              
                                                                          
You should have received a copy of the GNU General Public License     
along with this program; if not, write to the Free Software               
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA  

-----------------------------------------------------------------        
          
 
 */

/* Be sure to set the configuration word to 3f72 when programming the chip
   It's done in the makefile */



#define FOSC   16000000
#pragma  CLOCK_FREQ  16000000

#include "16f877.h"

//#define TMR0DIV   256-(FOSC/(8000*16)) //Compiler will not do this math!
//Divider constant for 8,000 interrupts per second

//For 8000 interrupts/sec
#define TMR0DIV 133

  

#define BAUD 9600
//#define BAUDDIV (FOSC/(BAUD*64)) - 1
#define BAUDDIV 26



/* these values written into ADCCON0 
   set the A-D channel mux address 
   and converison clock to 1/32 osc.
   This makes a 32uS converson time*/
#define  AD_0           0x81     /* ch 0 right front edge sensor*/
#define  AD_1           0x89     /* ch 1 left front edge sensor*/
#define  AD_RMFB        0x91     /* ch 2 Right motor feedback*/
#define  AD_LMFB        0x99     /* ch 3 Left motor feedback*/
#define  AD_4           0xa1     /* ch 4  Drive motor current 1v/amp*/
#define  AD_5           0xa9     /* ch 5  IR recv pulse amplitude    */
#define  AD_6           0xb1     /* ch 6  unused */
#define  AD_7           0xb9     /* ch 7  Battery voltage divided by 3    */    

char tx_buf[34]@0x24;     /* Tx serial port buffer */
char iavg[4]@0x20;




/* Analog inputs */
char  speed;

char  rmfb;
char  lmfb;

//char  mode;


char  right_speed,right_prm;
char  left_speed,left_prm;

char  bot_mode;

char  IR_sens;
 

#define MODE_STOP 0

#define MODE_RUN 1

#define MODE_GOHOME 7
#define MODE_NULL 0xff

#define REV0 0xf9
#define REV1 0xf6 
#define REV2 0xf2
#define REV3 0xed
#define REV4 0xe7
#define REV5 0xd8
#define FWD0 7
#define FWD1 10
#define FWD2 14
#define FWD3 19
#define FWD4 25
#define FWD5 40




char  prescale;
char  timer;
char  prm_ctl;
/* bits in prm_ctl */
#define  R_fwd 0
#define  L_fwd 1


//Port C bits

#define R_EDGE_LED  0  /* Low true output turns on Right Front edge detect IR LED */
#define L_EDGE_LED 1  /* Low true output turns on Left Front edge detect IR LED */

//PORT D bits
#define R_LED 0      /* Low true output turns on Right Red indicator LED */
#define M_LED 1      /* Low true output turns on Middle Green indicator LED */
#define L_LED 2      /* Low true output turns on Left Red indicator LED */

/* Keep the duty cycle of the following IR LEDs to 5% or less or they may burn out */
#define R_REFL_LED   6  /* HIGH true output turns on Right object detector IR LED */
#define L_REFL_LED   7  /* HIGH true output turns on Left object detector IR LED */



char  workB;

/* Port B motor control bits */

#define  LeftEnable 5    /* Left Motor pwm (L293D enable enable)*/
#define  RightEnable 4   /* Right Motor pwm (L293D enable enable)*/
#define  FwdLeft  3     /*Left Motor forward */
#define  RevLeft  2     /*Left Motor reverse*/
#define  FwdRight 1     /*Right Motor forward */
#define  RevRight 0     /*Right Motor reverse */



#define  P_width  22    /*Motor pulse width in interrupt ticks*/
char tx_ptr,rx_ptr,txstate,rxstate;
char  crcH,crcL;

char r_speed;
char l_speed;
char l_integrate;
char r_integrate;
char dir_ctl;

char testmode;
char speed_to_pulse_rate(char speed);


char timer2,startup_timer,motor_timer,tilt_dir, escape_timer;
char tilt_memory, border_memory, pushback_memory, cruse_memory; 

char  counter1; 
char  t8k_timer;     /* 8000 ticks/sec down counter */
char   runTimer_H;  /* measures run time in seconds */
char   runTimer_L;
char spi_stat;
char  battery;
char  drive_current, drive_current_avg;


char flags, arb_code;
char debug;
char mon_dir_ctrl;
char  lf_sens, rf_sens;

char cruse_output, chase_output , current_limit_output , border_output;
char check_battery_output, continue_output, arbitrate_output;



char l_IR, r_IR, amb_light; 

char lf_avg,rf_avg,lr_avg,rr_avg, f_ratio, r_ratio;

char divide10;
char divide100;
char lr_ratio;




//Bits in flags variable
#define tick100 0
#define direction 1
#define r_odo_last 2
#define stalled 3
#define spin_left 4
#define spin_right 5
#define attack 6


char rnd;            /*random number*/
char ctr;           /* a counter */
char temp;




//----------------------------------------------------------




#define COUNT 1      /* offset to count field in tx/rx buffers */
#define ADDRESS 0    /* offset to address field in tx/rx buffers */
#define DATA 2       /* offset to start of data in tx/rx buffers */





char test_hi@0xfe;

char detect_line();
char neg(char x);
char integrate(char speed,char mfb,char integ);






//------------------------------------------------------------------

/* Interrupts from Timer 0 occur at about 8,000 per second. */
void interrupt(void)
{
   char R_pulse,L_pulse,motor_avg;
   char i,l,r,spidata;
   
   set_bit(PORTD,4);
  
   if (INTCON & 4) {   //Check for a TMR0 interrupt

      

      clear_bit(INTCON,2);      //Clear timer 0 interrupt flag
      TMR0 = TMR0DIV + TMR0;       //restart timer 0
      
      if(t8k_timer) t8k_timer--; //8000 ticks per second timer decrement

      if(prescale-- == 0){
         
         prescale = 79;
         if(timer != 0) timer--;    //10 ms pertick timer
         if(timer2 != 0) timer2--;
         if(motor_timer != 0) motor_timer--;
         
      
                 
         if(divide10++ >= 9){
             
             if(startup_timer != 0)    startup_timer--; //100ms per tick timers
             if(escape_timer != 0)     escape_timer--;
             if(cruse_memory != 0)     cruse_memory--;
             if(pushback_memory != 0)  pushback_memory--;
             if(border_memory != 0 )   border_memory--;
             if(tilt_memory != 0 )     tilt_memory--;
             
             divide10 = 0;
             set_bit(flags,tick100);
                                       
         }

         if(divide100++ >= 99){  // 1 second per tick timer
            runTimer_L++;
            if(runTimer_L == 0) runTimer_H++;
            divide100 = 0;

            
         }

      }


      

      PORTB = workB;       //output the prm motor control bits to port B
      
      workB = 0;
      

         /* adjust right pulse rate modulator */
         if (right_prm < P_width) {
            set_bit(workB,RightEnable);
            if (prm_ctl & (1 << R_fwd))
               set_bit(workB,FwdRight);
            else
               set_bit(workB,RevRight);
         }
         if (right_prm-- == 0) {
            right_prm = speed_to_pulse_rate(right_speed) + P_width;
            if (right_speed > 127) clear_bit(prm_ctl,R_fwd);
            else set_bit(prm_ctl,R_fwd);
         }

         /*adjust left pulse rate modulator */
         if (left_prm < P_width) {
            set_bit(workB,LeftEnable);
            if (prm_ctl & (1 << L_fwd))
               set_bit(workB,FwdLeft);
            else
               set_bit(workB,RevLeft);
         }

         if (left_prm-- == 0) {
            left_prm = speed_to_pulse_rate(left_speed) + P_width;
            if (left_speed > 127) clear_bit(prm_ctl,L_fwd);
            else set_bit(prm_ctl,L_fwd);
         }


      }
   
    if (bot_mode == MODE_STOP) workB = 0;    //Stop the bot.
      
    if ((l_speed == 0) && (r_speed == 0)) workB = 0;
    if(testmode == 1) workB = 0;
      
      //Make a new random number
      if (rnd & 0x80) { //rnd msb is 1
            asm{
               movlw 1ch ;
               xorwf _rnd,F;
               bsf   STATUS,C;
               rlf   _rnd; //8 bit left shift
              
            }
         } else {    //rnd msb  is 0
            asm{
               bcf   STATUS,C;
               rlf   _rnd; //8 bit left shift
               
            }
         }
       
      

    clear_bit(PORTD,4);        

   }
//--------------------------------------------------------------
short mpy(char a, char b)
{
   return a * b;
}
//---------------------------------------------------------------
char divide(char a, char b)
{
   return a / b;
}

   //-----------------------------------------------------------------------

   // compute 16 bit CRC on 1 data byte. 
   //   crcH and crcL  are global variables which accumulate the 16 bit CRC. 
   //   They must be cleared before starting to compute 16 bit CRC on a string.
   //   The final output value will be in crcH and crcL.
   
   void crc(char data){

      char i;
     // short crc16;

      for (i=0;i<8;i++) {                //Do all 8 bits in the data byte
         if (data & 0x80) crcH ^= 0x80; //if data bit is 1 then flip crc msb
         data = data << 1;             // get next data bit
         if (crcH & 0x80) { //crc msb is 1
            asm{
               bcf   STATUS,C;
               rlf   _crcL; //16 bit left shift
               rlf   _crcH;
               movlw 80h;
               xorwf _crcH,F; //xor with 0x8005
               movlw 5;
               xorwf _crcL,F;

            }
         } else {    //crc msb  is 0
            asm{
               bcf   STATUS,C;
               rlf   _crcL; //16 bit left shift
               rlf   _crcH;
            }
         }
      }

   }
   //-----------------------------------------------------------------------
   void set_tx_buffer_crc(){
      int j = tx_buf[COUNT + 0] + 2; //get data size
      int i;

      crcH = 0;         //Clear crc16
      crcL = 0;
      for (i=0;i<j;i++) crc(tx_buf[i]); //Compute crc16 over buffer
      tx_buf[i++] = crcH;      //tack the crc bytes on the end of the buffer
      tx_buf[i++] = crcL;
      txstate = 0;            //State 0 = stopped
   }

   //-----------------------------------------------------------------------
   
   void make_info_pkt(){
      char i,j;
      i = ADDRESS;
      tx_buf[i] = 1;             // send to master
      i = COUNT;
      tx_buf[i] = 16;            // n bytes
      i = DATA;
      tx_buf[i++] = 0x01;        //data type = 1
      tx_buf[i++] = l_speed;        //1
      tx_buf[i++] = r_speed;        //2
      tx_buf[i++] = flags;          //3
      tx_buf[i++] = runTimer_H;     //4
      tx_buf[i++] = runTimer_L;     //5

      tx_buf[i++] = l_IR;           //6
      tx_buf[i++] = r_IR;           //7
      tx_buf[i++] = amb_light;      //8 
      tx_buf[i++] = bot_mode;       //9
      
      tx_buf[i++] = battery;        //10 Battery voltage/3
      tx_buf[i++] = mon_dir_ctrl;   //11
      tx_buf[i++] = timer;          //12
      tx_buf[i++] = lf_sens ;       //13  Left front line sensor
      tx_buf[i++] = rf_sens ;       //14  Right front line sensor
      tx_buf[i++] = drive_current; //15
      tx_buf[i++] = arb_code;      //16
      
      
      
      crcH = 0;
      crcL = 0;
      set_tx_buffer_crc();  //compute and add CRC16 bits to end of pkt

      txstate = 1;          //Tell scheduler it's ready to transmit
   }
   
   //----------------------------------------------------------------------




  //send character if tx ready and return true 
  //  else return false if tx not ready 
   char tx_byte(char c){
      if (PIR1 & (1 << TXIF)) {
         TXREG = c; 
         return 1;     
      } else
         return 0;
   }

 
  //-----------------------------------------------------------------------


   void send_tx_buffer(){
      static char j;

      
      switch (txstate) {
      case 1:
      case 2:
      case 3:  if (tx_byte(0xff)) txstate++;
         break;
      case 4:  if (tx_byte(0xf0)) txstate++;
         break;
      case 5:  if (tx_byte(0x55)) txstate++;
         break;
      case 6:  tx_ptr = 0;
         j = tx_buf[COUNT + 0] + 4; //Must use COUNT+0 to force indirect addressing
         txstate++;
         break;

      case 7:  if (tx_byte(tx_buf[tx_ptr])) {
            j--;
            tx_ptr++ ;
            if (j == 0) txstate = 8;
         }
         break;

      case 8:  if (tx_byte(0x33)) {
            txstate = 0;
         }



      }

      
   }

   

      
   //-----------------------------------------------------------------------
   /* Convert a signed value to an absolute value between 127 and 0 
        0 becomes 127
      127 becomes 0
     -128 becomes 0
     
   */
   char speed_to_pulse_rate(char speed)
   {
      if (speed > 127) {      //See if speed is negative !
         return speed & 0x7f;
      } else {
         return speed ^ 0x7f;
      }



   }

   //----------------------------------------------------------------------
   char ad_convert(char channel)
   {  char x;
      
      
      ADCON0 = channel;
      for (x=16;x>0;x--);         //wait at least 20 us for data to stabilize
      
      set_bit(ADCON0,GO_DONE);   //start A-D conversion

      clear_bit(PORTD,R_REFL_LED); //turn off both IR object detect LEDs
      clear_bit(PORTD,L_REFL_LED);
      
      while (ADCON0 & (1 << NOT_DONE));  //wait for conversion to complete
      
      return ADRESH;          //Return unsigned result
   }

   

   //---------------------------------------------------------------------

   void get_AD_values(){
    
    
    drive_current = ad_convert(AD_4);  //Read unsigned drive motor current 1v/amp
    battery = ad_convert(AD_7);        //Read battery voltage/3
    clear_bit(PORTC,R_EDGE_LED) ;      //White line sensor Right IR emitter ON
    rf_sens = ad_convert(AD_0);        //Read right front sensor
    set_bit(PORTC,R_EDGE_LED);         //White line sensor Right IR emitter OFF
    clear_bit(PORTC,L_EDGE_LED);       //White line sensor Left IR emitter ON
    lf_sens = ad_convert(AD_1);        //Read left front sensor
    set_bit(PORTC,L_EDGE_LED);         //White line sensor Left IR emitter OFF
    

   }

   //----------------------------------------------------------------------
   
  
   void adjust_motor_speed(){
      char i;
    
      rmfb = ad_convert(AD_RMFB)+128; //get right motor feedback as signed value
      lmfb = ad_convert(AD_LMFB)+128; //get left motor feedback  as signed value
    
      for (i=0;i<10;i++) {  //Adjust motor speeds based on feedback values
     
        r_integrate = integrate(r_speed,rmfb,r_integrate);
        l_integrate  = integrate(l_speed,lmfb,l_integrate);
        right_speed = r_integrate;
        left_speed  = l_integrate;
       
      }
   }
  //----------------------------------------------------------------------
 
   //dir_control constants.
   
   #define FWD 1
   #define FWD_LEFT 2
   #define FWD_RIGHT 3
   #define FWD_HARD_LEFT 4
   #define FWD_HARD_RIGHT 5
   #define FWD_MAX 6
   
   #define SPIN_LEFT 10
   #define SPIN_RIGHT 11
   #define STOP 12

   #define REV 16
   #define REV_LEFT 17
   #define REV_RIGHT 18
   #define REV_HARD_LEFT 19
   #define REV_HARD_RIGHT 20
   #define REV_MAX 21
   
   
   void dir_control(char value)
   {
      mon_dir_ctrl = value;
      if(value <= FWD_MAX)  set_bit(flags,direction) ; //Set forward flag
      if(value >= REV) clear_bit(flags,direction);     //or set the reverse flag
      

       switch(value){

       
       case FWD:     l_speed = FWD4;
                     r_speed = FWD4;
                     break;

       case FWD_MAX: l_speed = FWD5;
                     r_speed = FWD5;
                     break;

       case FWD_LEFT:
                     l_speed = FWD2;
                     r_speed = FWD5;
                     break;

       case FWD_RIGHT:
                     l_speed = FWD5;
                     r_speed = FWD2;
                     break;

       case FWD_HARD_LEFT:
                     l_speed = 0;
                     r_speed = FWD5;
                     break;

       case FWD_HARD_RIGHT:
                     l_speed = FWD5;
                     r_speed = 0;
                     break;

       case REV:     l_speed = REV4;
                     r_speed = REV4;
                     break;

       case REV_MAX: l_speed = REV5;
                     r_speed = REV5;
                     break;


       case REV_LEFT:
                     l_speed = FWD1;
                     r_speed = REV5;
                     break;

       case REV_RIGHT:
                     l_speed = REV5;
                     r_speed = FWD1;
                     break;

       case REV_HARD_LEFT:
                     l_speed = 0;
                     r_speed = REV5;
                     break;

       case REV_HARD_RIGHT:
                     l_speed = REV5;
                     r_speed = 0;
                     break;

       case SPIN_LEFT:
                     l_speed = REV4;
                     r_speed = FWD4;
                     break;

       case SPIN_RIGHT:
                     l_speed = FWD4;
                     r_speed = REV4;
                     break;

       case STOP:
      
                     l_speed = 0;
                     r_speed = 0;
                     break;

       }
   }


   
  //---------------------------------------------------------------------------------


   /* Saturating addition.  Result is clipped at +127 or -128 
      instead of overflowing.
      Note the parameters a and b and signed char values (-128..+127)
      but the compiler thinks they are unsigned values (0..255) so
      I had to do some strange looking things below.
      */
  
   char addsat(char a, char b)
   {  char r;
      if (a > 127) goto a_minus;  //See if a is minus
      if (b > 127) goto a_b_diff; //a is plus, check b for minusness

      r = a + b;                //Both a and b are positive numbers
      if (r > 127) r = 127; //clip at +limit
      return r;

      a_minus:
      if (b < 0x80) goto a_b_diff;  //A is minus, now check b and see if it's minus too
      r = a + b;
      if (r < 0x80) r = 0x80;  //clip at -128
      return r; 

      a_b_diff:
      return a + b;     //No clipping needed


   }
   
     //---------------------------------------------------------------------
   /* return the absolute value of x */
   
   char abs(char x){
      if(x > 127){
         x ^= 0xff;
         x++;
      }
      return x;
   }
   
   //-----------------------------------------------------------------------
   char abs_diff(char a, char b)
   {
      
      if(a == 0) return b;
      if(b == 0) return a;
      if(a > b) return (a - b);
         else return ( b - a) ;
      
   }

   //-----------------------------------------------------------------------
   /* return the negative of x */
   
   char neg(char x){
      x ^= 0xff;
      x++;
      return x;
   }
   

   //----------------------------------------------------------------------
   /* return x if its 0 or less else return 0 */
   
   char clip_pos(char x){
      if(x < 128) x = 0;
      return x;
   }
   

   //----------------------------------------------------------------------
   /* return x if it's 0 or higher else return 0 */
   
   char clip_neg(char x){
      if(x > 127) x = 0;
      return x;
   }
   
   //---------------------------------------------------------------------
   //return the a 16 bit value
   char sign16(int x){
      char rv;
      rv = 0;
      if(x & 0x8000) rv = 1;
      return rv;
   }
   //---------------------------------------------------------------------

   //Limit x to +/- l
   char limit(char x, char l){

      if(x & 0x80){
         if( x < neg(l)) return neg(l);
         else return x;
      }
      if( x > l) return l;
      else return x;


   }
   //-----------------------------------------------------------

   char divideby2(char x){
      if(x < 128) return (x >> 1);
      else{
         return (x >> 1) | 0x80;
      }
   }

   //-------------------------------------------------------------------
   char ratio(char a, char b)
   {  short d;
      char c;
      if((a == 0) && (b == 0)) return 0;
      c = abs_diff(a,b);
      d = c * 256;
      d = d -1;
      if(a > b) c = a ; else c = b;
      if(c == 0) return 255;
       else return (d / c);
   }

   //----------------------------------------------------------------------
   char integrate(char speed,char mfb,char integ)
   {
      speed = speed + 128;   //convert to unsigned
      mfb = mfb + 128;
      if (speed > mfb) {
         integ++;
         if (integ == 0x80) integ--;  //Clip at +127
         return integ;
      } else {
         integ--;
         if (integ == 0x7f) integ++;  //Clip at -128
         return integ;
      }



   }
   //-----------------------------------------------------------------------
   
   #define IR_MIN 180  
   
   /*Reverse directon when we see the white border line */
   /* Note: IR readings sit at 250 to 255 on black and
      drop to about 110 on white. */

   void check_border()
   {  static char action;
      static char lock;
      char time;
      

    
     
         if(lock != 1){
            action = 0;

            if(lf_sens < IR_MIN){
               action = REV_RIGHT;
               time = 10 + (rnd & 7);
            }
         

            if(rf_sens < IR_MIN){
               action = REV_LEFT;
               time = 10 + (rnd & 7);
            }
               
         

            if((lf_sens <  IR_MIN) && (rf_sens < IR_MIN)){
               if(runTimer_L & 1){
                  action = REV_LEFT;     //random left or right turnaround
               }else{
                  action = REV_RIGHT;
               }
               time = 12;
            }

            if(action){
               border_memory = time;      //timeout
               border_output = REV;       //Initially backup 
               lock = 1;
            }
         }


         
     

     if(border_memory){
        if((lf_sens <  IR_MIN) || (rf_sens < IR_MIN))
           border_output = REV;            //Backup until sensors see black again           
        else 
           border_output = action;         //Then execute the turn-around
        
     } else{
        border_output = 0;
        time = 0;
        lock = 0;
     }


   }
 //------------------------------------------------------------------------
  
   void cruse()
   {  
      cruse_output = FWD;
     // if(cruse_memory == 0) cruse_memory = 12;
     // if(cruse_memory > 0) cruse_output = SPIN_RIGHT ;
    //  if(cruse_memory > 6) cruse_output = FWD;
          
   }
   
 //-----------------------------------------------------------------------

 #define lmin 8
 
 void chase()
   {  
      
      chase_output = 0;
      set_bit(PORTD,M_LED);   //Attack indictor LED off
      clear_bit(flags,attack);
      set_bit(PORTD,R_LED);
      set_bit(PORTD,L_LED);

      if((l_IR > lmin) || (r_IR > lmin)){
         if(ratio(l_IR,r_IR) > 150){
            if(l_IR > r_IR){
               chase_output = FWD_LEFT;
               clear_bit(PORTD,L_LED) ;
            }
               else{
                  chase_output = FWD_RIGHT;
                  clear_bit(PORTD,R_LED);
               }
         }else{
            chase_output = FWD_MAX;
            set_bit(flags,attack);
            clear_bit(PORTD,M_LED);    //Turn on green attack LED
         }
      }

      

      
      
   }
   //-----------------------------------------------------------------------

   //Stop motors while current exceeds I .
   void limit_motor_current(char I){

       if(drive_current > I){   
          current_limit_output = STOP;
       }else{
          current_limit_output = 0;
       }

   }

   //-------------------------------------------------------------------------
   //Stop motors while battery reads less than 5.5 volts (or whatever "low_limit" is)
   void check_battery(char low_limit){
      if((battery < low_limit) && (runTimer_L > 6)){ //After 6 secs and bat less than 5.5 volts.
         check_battery_output = STOP;
      } else{
         check_battery_output = 0;
      }

   }

   //----------------------------------------------------------------------
   //IR object detector processing.  Normal ambiant light reading is about 50.
   void process_IR()
   {  
      
      amb_light = ad_convert(AD_5);             //Read ambiant light value 
      if(amb_light > 100) return;               //Don't process if blinded by external IR pulse

      set_bit(PORTD,R_REFL_LED);                //Right object detect IR LED on
      r_IR = ad_convert(AD_5)  ;               //Read value , IR LED is turned off by ad_convert()
      if(r_IR > amb_light)
         r_IR = r_IR - amb_light;
      else r_IR = 0;

      set_bit(PORTD,L_REFL_LED);                //Left object detect IR LED on
      l_IR = ad_convert(AD_5) ;                 //Read value , IR LED is turned off by ad_convert()
      if(l_IR > amb_light)
         l_IR = l_IR - amb_light;
      else l_IR = 0;

      clear_bit(PORTD,R_REFL_LED); //Make sure both LEDs are off
      clear_bit(PORTD,L_REFL_LED);

  }

   //------------------------------------------------------------------------

  // Subsumption arbitration happens here.
   void arbitrate(){

      
     arb_code = 0;
     if(cruse_output) { arb_code = 1; dir_ctl = cruse_output; }                 //Lowest priority
     if(chase_output) { arb_code = 2; dir_ctl = chase_output; }
     
     
     if(border_output) { 
        arb_code = 5; 
        dir_ctl = border_output;
     }
     
     if(current_limit_output) { arb_code = 6; dir_ctl = current_limit_output;}
     if(check_battery_output) { arb_code = 7; dir_ctl = check_battery_output; } //Highest priority
     
     dir_control(dir_ctl);   //Now tell the motors what to do.
     
   }

   //-------------------------------------------------------------------------
     
   
   main()
   {
      char i;
      char x;
      char y;
      char z;
      
    
      test_hi = 0;

      INTCON = 0;
      STATUS = 0;
      PORTA  = 0;
      PORTB  = 0;
      PORTC  = 3;
      PORTD  = 0x3f ;
      T1CON  = 0;
      TMR0   = 0;
      workB  = 0x20;
      

      tx_ptr = 0;
      rx_ptr = 0;
            
      RCSTA = 0x90;             //SPEN + CREN (configure serial port)


      set_bit(STATUS,RP0);     //Bank1
      

      set_tris_b(0x00);        //Port B bits are outputs
      set_tris_c(0xc0);        //Port C outputs except 6:7 are UART pins 
      TRISA = 0xff;            //port A all analog inputs
      TRISD = 0;              //port D outputs
      TRISE = 0x7;           //port E analog inputs
      
      OPTION_REG = 0x01;       //Prescaler 1:4 assigned to Timer 0, pullups on portB
      ADCON1 = 0;              //Set all port A to analog with VREF=VCC
      TXSTA = 0xa2;            //Set tx usart status/ctrl reg= CSRC + TXEN + TRMT
      SPBRG = BAUDDIV;         //Set baudrate
      //SSPSTAT = 0x00;          //SPI PORT   slave mode CKE = 0  SMP = 0
      PIE1 = 0;                //Disable all peripheral interrupts
      //set_bit(PIE1,SSPIE);     //Enable SPI port interrupts
      clear_bit(STATUS,RP0);   //Bank0
      
      //SSPCON = 0;
      //SSPCON = 0x15;            // SPI slave mode -SS disabled  clock = SCK pin  CKP=1
      //set_bit(SSPCON,SSPEN);    //Enable SPI port

      clear_bit(INTCON,T0IF);  //Clear Timer 0 interrupt flag
      TMR0   = TMR0DIV;        //Start Timer 0
      set_bit(INTCON,T0IE);    //Enable Timer 0 interrupts
      set_bit(INTCON,PEIE);   //Enable peripheral interrupts
      set_bit(INTCON,GIE);     //Enable global interrupts
      iavg[0] = 0;
      iavg[1] = 0;
      iavg[2] = 0;
      iavg[3] = 0;
      drive_current_avg = 0;
      txstate = 0;

      
      clear_bit(PORTD,M_LED);     //green indicator LED on
      
      testmode = 0;
      startup_timer = 50;
      tilt_memory = 0;
      border_memory = 0;
      pushback_memory = 0;
      cruse_memory = 0;
      timer2 = 0;
      flags = 0;
      divide10 = 0;
      divide100 = 0;
      counter1 = 10;
      runTimer_H = 0;
      runTimer_L = 0;
      left_speed = 0;
      right_speed = 0;
      r_integrate = 0;
      l_integrate = 0;
      r_speed = 0;
      l_speed = 0;
      speed = 0;
      lf_sens = 256;
      rf_sens = 256;
      
      bot_mode = MODE_STOP;
      dir_ctl = STOP;
      mon_dir_ctrl = dir_ctl;
      arb_code = 0;

      

      
   
      /* Wait here for 5 seconds after power up */
      startup_timer = 50;             //5 sec
      while(startup_timer > 0){               //Wait 5 sec before starting
         clear_bit(PORTD,3);
         if(startup_timer & 4){
             clear_bit(PORTD,M_LED);
             
         }
            else{
                set_bit(PORTD,M_LED); // blink the green LED during the 5 sec wait.
                
            }

         get_AD_values();
         if(t8k_timer == 0){
           t8k_timer = 16;      //2ms timeout value
           process_IR();      //Get info from IR object detector
        }
         
         chase();    //Refresh Indicator LEDs based on IR sensors

         if (txstate == 0) make_info_pkt(); //Get new data for transmission
         send_tx_buffer();  //Send data on RF link if TX ready
         set_bit(PORTD,3);
                  
      }

      clear_bit(PORTD,3); //test
      set_bit(PORTD,M_LED);  //Indicator LED off
      bot_mode = MODE_RUN; //Allow motors to run
      t8k_timer = 16;  //timeout in 2ms
      
      /* Start of the main program loop */

      for(;;){
      
       
       if (txstate == 0) make_info_pkt(); //Get new data for transmission
       send_tx_buffer();  //Send data on RF link if TX ready

       

       if(timer2 == 0){
           get_AD_values(); //Every 10ms read the A to D converters
           timer2 = 1;
       }

       /* Now check all the sensors */
       
       check_border();
       cruse();
       chase();
      
       clear_bit(PORTD,3); //test

       limit_motor_current(30);  // 600 MA Limit
       check_battery(93);        //5.5 volt lower limit

       set_bit(PORTD,3); //test

       // Sort it all out and decide what to tell the motor controller.
       arbitrate();
       
        

       adjust_motor_speed();
        
        if(t8k_timer == 0){
           t8k_timer = 16;      //2ms timeout value
           process_IR();      //Get info from IR object detector
        }
        
        if(flags & (1 << tick100)){    //Every 100 ms do this...
             iavg[3] = iavg[2];        //Average the motor current over 400ms
             iavg[2] = iavg[1];
             iavg[1] = iavg[0];
             iavg[0] = drive_current;
             drive_current_avg = 0;
             for(i=0;i<4;i++) drive_current_avg = drive_current_avg + iavg[i];
             drive_current_avg = drive_current_avg >> 2;  //div by 4
             clear_bit(flags,tick100);
        } 
      
      }   //end main loop

   


} //End main()
/* End of source */

sumo-robot-robots-projekt-l293-motor-kontrol-robotlar-1

sumo-robot-yarismasi-robotlar-yarisiyor-2

sumo-robot-mini-mikrocontroller-delta-force-robotic-rally-3

robot-devresi-robors-circuits-4

sumo-robotun-mekanik-saft-lastik-tekerlek-motorlari-5

Kaynak: http://www.wa4dsy.net/robot/deltaforce/ Alternatif linlk: Mini Sumo Robot L293D PIC16F877

Dosya indirme LINK listesi (TXT formatında) link-13548.zip şifre-pass: 320volt.com

  • Uziel

    no podrias subir un archivo donde venga todo a detalle de como hiciste el robot mini sumo por favor.