Unidad de control de un motor de gasolina

Unidad de control de un motor de gasolina

 

La idea u objetivo del proyecto es controlar un motor de un automóvil, para después de ponerlo en funcionamiento,  poder controlar diferentes reacciones. Para ello hemos creado una CPU o Unidad de control que controle diferentes parámetros. También se conoce como centralita y su función es controlar varios parámetros para poder dar respuesta a las peticiones del usuario. El motor es de la marca OPEL, tiene 4 cilindros y en cada cilindro tiene un inyector y una bujía para poder crear la combustión  necesaria para su funcionamiento.

La CPU o Unidad de control debe controlar los siguientes parámetros:

  • Cantidad de masa de aire de entrada al motor en porcentajes (%0, %5, %25, %50, %75, %100).
  • Tiempo de inyección de gasolina en milisegundos (de 0ms a 16ms).
  • Angulo de avance del salto de chispa respecto al PMS (Punto muerto superior) y PMI (Punto muerto inferior). También conocido como ángulo Dwell.

Para poder controla todos estos parametros tendremos una señal situada en el motor.

Esta señal nos la proporcionara un sensor inductivo situado en el bolante motor. Interpretando esta señal y conociendo los diferentes parámetros debemos dar respuesta a las peticiones del usuario.

 

Tiempo de inyeccion y angulo Dwell
(Alimentacion, etapa de control y etapa de potencia)

.
Medidor de masa de aire
(Etapa de control )
.
(Etapa de potencia; puente en H)
.
.
.
PROGRAMA
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*********************************************************************
*********************************************************************
                 AUTOAREN CPU OPEL 2000 16v
                 MOTOREAN PROBATZEKO BERTSIOA
********************************************************************
OPEL: Sensor Inductivo: 57+1 Dientes=58 flanko positibo
                                                    Tiempo inyeccion+Angulo Dwell
*********************************************************************/
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <16F877.H>  //16F877 PIC-a erabiliko dugu Inyekzioa eta txispa kontrolatzeko
#device ADC=10       //Bihurgailu analogiko/digitalak 10 byte edukiko ditu//1024
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4M) //4MHz-tako kristal harria
#use RS232(baud=19200, xmit=PIN_C6, rcv=PIN_C7,DISABLE_INTS)//Serie Portua
#include <math.h>                                           //19200Abiadura//Pin C6 datuak bidaltzeko
                                                            //Disable_Ints Etendurak desabilitatzen ditu RS232 Serie Portutik                    datuak bidaltzerakoan
int1 k=0;         //RPM-ak kalkulatzeko agindua
float t1=0;       //Hortzen arteko oraingo denbora
float t2=0;       //Hortzen arteko aurreko denbora
int8 kont_dient=0;  //Bira batean hortz kopurua
float aux_rpm=0;  //Abiadura RPM-tan
int16 rpm;        //Abiadura RPM-tan
int16 t_grado;    //Gradu bat igarotzeko behar den denbora
int16 pot_iny;    //Inyekzio denbora; Potentziometroa balio digitala
int16 pot_av;     //Angulo Avance; Potentziometroa balio digitala
int16 VDmax=1024; //Balio digital maximoa;ADC=10(byte) bada->1024/ADC=8(byte) bada->255
int8 Tmax=17;     //Inyekzio denbora maximoa
int8 T=0;         //Inyekzio denbora
int8 Gmax=43;     //Gradu maximoa ez errealak;24 gradu negatibo+18 gradu positibo=42 gradu guztira
int8 G=0;         //Graduak ez errealak; 0 gradutik 43 gradu arte
signed int8 Gr=0; //Gradu errealak; Gradu ez errealak-24
float a=0;        //Hortzetik hortzera dagoen denbora segunduetan, hau da t1-etik t2-ra dagoen denbora
float b=0;        //1 bira zenbat segundu diren kalkulatzeko;1 bira = 360º = 58 flanko positibo = 60 hortz
int8 i;
char bidali[7];   //Portu serietik bidaltzeko datuak;
                  //rpm (2 digitu)/angelu (zeinua + 2 digitu)/inyekzio (2 digitu)
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/********************************************************************
   Interrupcion TIMER 2 Etendura
   Inyekzioa mozteko erabiliko dugu
********************************************************************/
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#int_timer2
void tiempo2(void)
{
   output_low(PIN_C2);  //Inyektorea itzali
   output_low(PIN_C3);  //Inyektorea itzali
   disable_interrupts(INT_TIMER2);   //Timer 2 Etendura desaktibatu
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**********************************************************************
   Kampoko Etendura PIN_B0
   Birak kontatzeko erabiliko dugu
***********************************************************************/
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#int_ext
void birak(void)
{
   t1=get_timer1(); //2 hortzen harteko denbora hartu//get timer-aren bidez momentuan timerraren akumulagailuan dagoen balioa artuko du
   set_timer1(0);  //Timer1 Hasieratu, momentu honetan timer-a kontatzen hasiko da
   if((t1>1.5*t2)||(kont_dient>=58))    //Oraingo denbora, aurreko denbora baino andiagoa bada
   {                                   //PMS -ean dagoela esan nahi du beraz kontaketa hasi
      kont_dient=1;
   }
   else
   {
      kont_dient ++; //Kont_dient inkrementatu
      if((kont_dient==5)||(kont_dient==34)) //Gasolina inyektatu
      {
         output_high(PIN_C2); //Inyectar
         output_high(PIN_C3); //Inyectar
         setup_timer_2 ( T2_DIV_BY_16,pot_iny/4,4 ); //Timer 2 konfiguratu//Inkrementu bakoitzak 16uS,potentziometroaren bidez kargatu behar dugun balioa artuko du.
         set_timer2(0); //Timer2 Hasieratu//etendura abilitatu bezahin laster asiko da kontaketa gainezka egin arte, timer-ak gainezka egitean etendurara joango da eta inyektoreak itzali egingo ditu
         enable_interrupts(INT_TIMER2);   //Timer 2 Etendura aktibatu
      }
      if(kont_dient==10)    //RPM-ak kalkulatzeko
      {
         k=1;
      }
   }
   t2=t1; //Oraingo denbora aurreko bezala gorde
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**********************************************************************
   Funtzio Nagusia
**********************************************************************/
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void main(void)
{
   delay_ms(2000);
   setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_1 );  //Timer 1 konfiguratu//Inkrementu bakoitzak 1uS
   set_timer1(0);  //Timer1 Hasieratu
   //setup_timer_0 ( RTCC_INTERNAL | RTCC_DIV_64 );   //Timer 0//0-16,320ms//Inkrementu bakoitzak 64uS
   //set_rtcc(0); //Timer0 hasieratu
   setup_timer_2 ( T2_DIV_BY_16,0xff,4 );   //Timer 2 konfiguratu//Inkrementu bakoitzak 16uS
   set_timer2(0); //Timer2 Hasieratu
   enable_interrupts(INT_TIMER2);   //Timer 2 Etendura aktibatu
   enable_interrupts(GLOBAL);       //Etendura guztiak aktibatu
   enable_interrupts(INT_EXT); //Kampoko etendura aktibatu B0 portua, B0 portuan kanpoko seinale bat jasotzean programa nagusia utzi eta programa zati zehatz batetara joaten da
   ext_int_edge(H_TO_L);      //Kampoko etendura aktibatu LtoH(goranzko flankoa), hau da 0v-tik 5v-rako aldaketa somatzen duenean exekutatzen hari den programa utzi eta int_ext etendurara joango da bertan dauden aginduak exekutatzeko
   setup_adc_ports(AN0_AN1_AN3);      //PIN A0,A1 eta A3 Analogiko bezala konfiguratu, hau da pin hauetan balio analogiko bat sartuko dugu eta pic-ak balio hau digital bihurtuko du//ADC=10 bada 10 byteraino hau da 1024 arteko balio tartea// ADC=8 bada 8 byterain, hau da 255 arteko balio tartea.
   setup_adc(adc_clock_internal);    //CAD Konfiguratu
   while(1)
   {
      //RPM//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
      if(k==1)
      {
         a=((t1/1000.0)/1000.0); //Hortzetik hortzera dagoen denbora microsegundutatik segundutara pasatu //3300uS = 0,0033s
         b=a*58.0;       //1 bira zenbat segundu diren kalkulatzeko// Motorrean 58 hortz
         aux_rpm=60.0/b; //Bira kopurua minutuko RPM    //60/0,2=300rpm
         rpm=aux_rpm;    //aux_rpm:float/rpm:int16
         k=0;            //RPM-ak kalkulatzeko balioa 0-an jarri
      }
      //TIEMPO INYECCION/////////////////////////////////////////////////////////////////////////////////////////////////////
      set_adc_channel(0);   //A0 kanala aktibatu
      delay_us(10);
      pot_iny=read_adc();   //A0-tik sartutako balioa irakurri
      T=pot_iny*Tmax/VDmax; //Inyekzio denbora milisegundutan
      //ANGULO AVANCE////////////////////////////////////////////////////////////////////////////////////////////////////////
      set_adc_channel(1);   //A1 kanala aktibatu
      delay_us(10);
      pot_av=read_adc();    //A1-etik sartutako balioa irakurri
      G=pot_av*Gmax/VDmax;  //Angulo avance gradutan
      Gr=G-24;
      //DATUAK EGOKITU///////////////////////////////////////////////////////////////////////////////////////////////////////
      bidali[0]=rpm/1000;   bidali[0]=bidali[0]+0x30;//RPM; Milakoak kalkulatu eta ASCII kodera pasa
      bidali[1]=(rpm%1000)/100;  bidali[1]=bidali[1]+0x30;//RPM; Ehunekoak kalkulatu eta ASCII kodera pasa
      if(Gr<0) //Angulo de Avance negatiboa
         bidali[2]=’-‘;
      else     //Angulo de Avance positiboa
         bidali[2]=’+’;
      bidali[3]=fabs(Gr)/10;   bidali[3]=bidali[3]+0x30;//Angulo de Avance; Hamarrekoa kalkulatu eta ASCII kodera pasa
      bidali[4]=fabs(Gr)%10;   bidali[4]=bidali[4]+0x30;//Angulo de Avance; Batekoak kalkulatu eta ASCII kodera pasa
      bidali[5]=T/10;   bidali[5]=bidali[5]+0x30;//Inyekzioa: Hamarrekoak kalkulatu eta ASCII kodera pasa
      bidali[6]=T%10;   bidali[6]=bidali[6]+0x30;//Inyekzioa; Batekoak kalkulatu eta ASCII kodera pasa
      //PORTU SERIEA RS232////////////////////////////////////////////////////////////////////////////////////////////////////
      disable_interrupts(global);   //Etendurak desaktibatu
      putc(‘Z’); //Komunikazioa hasteko marka
      for(i=0;i<7;i++)
         putc(bidali[i]);  //Datuak bidali portu serietik
      enable_interrupts(global); //Etendurak aktibatu
     //BUJIAK////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
      if((Gr<=18)&&(Gr>12))   //18º
      {
         while(kont_dient!=3)
         {
            output_high(PIN_C0); //Bujias 1-4 kargatu
            output_high(PIN_C1); //Bujias 2-3 kargatu
         }
         output_low(PIN_C0); //Bujias 1-4 Deskargatu!!¡!¡!
         delay_us(500);
         while(kont_dient!=32)
         {
            output_high(PIN_C0); //Bujias 1-4 kargatu
            output_high(PIN_C1); //Bujias 2-3 kargatu
         }
         output_low(PIN_C1); //Bujias 2-3 Deskargatu!!¡!¡!
         delay_us(500);
      }
      else if((Gr<=12)&&(Gr>6))  //12º
      {
         while(kont_dient!=2)
         {
            output_high(PIN_C0); //Bujias 1-4 kargatu
            output_high(PIN_C1); //Bujias 2-3 kargatu
         }
         output_low(PIN_C0); //Bujias 1-4 Deskargatu!!¡!¡!
         delay_us(500);
         while(kont_dient!=31)
         {
            output_high(PIN_C0); //Bujias 1-4 kargatu
            output_high(PIN_C1); //Bujias 2-3 kargatu
         }
         output_low(PIN_C1); //Bujias 2-3 Deskargatu!!¡!¡!
         delay_us(500);
      }
      else if((Gr<=6)&&(Gr>0)) //6º
      {
         while(kont_dient!=1)
         {
            output_high(PIN_C0); //Bujias 1-4 kargatu
            output_high(PIN_C1); //Bujias 2-3 kargatu
         }
         output_low(PIN_C0); //Bujias 1-4 Deskargatu!!¡!¡!
         delay_us(500);
         while(kont_dient!=30)
         {
            output_high(PIN_C0); //Bujias 1-4 kargatu
            output_high(PIN_C1); //Bujias 2-3 kargatu
         }
         output_low(PIN_C1); //Bujias 2-3 Deskargatu!!¡!¡!
         delay_us(500);
      }
      else if((Gr<=2)&&(Gr>=-2))    //0º
      {
         while(kont_dient!=58)//PMS//
         {
            output_high(PIN_C0); //Bujias 1-4 kargatu
            output_high(PIN_C1); //Bujias 2-3 kargatu
         }
         output_low(PIN_C0); //Bujias 1-4 Deskargatu!!¡!¡!
         delay_us(500);
         while(kont_dient!=29)//Erdia PMI//
         {
            output_high(PIN_C0); //Bujias 1-4 kargatu
            output_high(PIN_C1); //Bujias 2-3 kargatu
         }
         output_low(PIN_C1); //Bujias 2-3 Deskargatu!!¡!¡!
         delay_us(500);
      }
      else if((Gr<0)&&(Gr>=-6))  //-6º
      {
         while(kont_dient!=57)
         {
            output_high(PIN_C0); //Bujias 1-4 kargatu
            output_high(PIN_C1); //Bujias 2-3 kargatu
         }
         output_low(PIN_C0); //Bujias 1-4 Deskargatu!!¡!¡!
         delay_us(500);
         while(kont_dient!=28)
         {
            output_high(PIN_C0); //Bujias 1-4 kargatu
            output_high(PIN_C1); //Bujias 2-3 kargatu
         }
         output_low(PIN_C1); //Bujias 2-3 Deskargatu!!¡!¡!
         delay_us(500);
      }
      else if((Gr<-6)&&(Gr>=-12))  //-12º
      {
         while(kont_dient!=56)
         {
            output_high(PIN_C0); //Bujias 1-4 kargatu
            output_high(PIN_C1); //Bujias 2-3 kargatu
         }
         output_low(PIN_C0); //Bujias 1-4 Deskargatu!!¡!¡!
         delay_us(500);
         while(kont_dient!=27)
         {
            output_high(PIN_C0); //Bujias 1-4 kargatu
            output_high(PIN_C1); //Bujias 2-3 kargatu
         }
         output_low(PIN_C1); //Bujias 2-3 Deskargatu!!¡!¡!
         delay_us(500);
      }
      else if((Gr<-12)&&(Gr>=-18))  //-18º
      {
         while(kont_dient!=55)
         {
            output_high(PIN_C0); //Bujias 1-4 kargatu
            output_high(PIN_C1); //Bujias 2-3 kargatu
         }
         output_low(PIN_C0); //Bujias 1-4 Deskargatu!!¡!¡!
         delay_us(500);
         while(kont_dient!=26)
         {
            output_high(PIN_C0); //Bujias 1-4 kargatu
            output_high(PIN_C1); //Bujias 2-3 kargatu
         }
         output_low(PIN_C1); //Bujias 2-3 Deskargatu!!¡!¡!
         delay_us(500);
      }
      else if((Gr<-18)&&(Gr>=-24))  //-24º
      {
         while(kont_dient!=54)
         {
            output_high(PIN_C0); //Bujias 1-4 kargatu
            output_high(PIN_C1); //Bujias 2-3 kargatu
         }
         output_low(PIN_C0); //Bujias 1-4 Deskargatu!!¡!¡!
         delay_us(500);
         while(kont_dient!=25)
         {
            output_high(PIN_C0); //Bujias 1-4 kargatu
            output_high(PIN_C1); //Bujias 2-3 kargatu
         }
         output_low(PIN_C1); //Bujias 2-3 Deskargatu!!¡!¡!
         delay_us(500);
      }
   }  //While(1)bukaera
}  //main() bukaera
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*********************************************************************
**********************************************************************
                 AUTOAREN CPU OPEL 2000 16v
                 MOTOREAN PROBATZEKO BERTSIOA
**********************************************************************
LCD
**********************************************************************/
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <16F876.H>//16F876 PIC-a erabiliko dugu datuak jaso eta LCD-an pantailaratzeko
#fuses XT,NOWDT,NOPROTECT
#use delay(clock=4M)
#use RS232(baud=19200, xmit=PIN_C6, rcv=PIN_C7) //Portu seriea Pin C6 datuak jasotzeko
#include «LCD.c»  //LCD-a erabiltzeko Programa gehigarria
char datuak[7];//Portu serietik jasotako datuak gordetzeko
int8 i;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/***********************************************************************
   Funtzio Nagusia
************************************************************************/
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void main(void)
{
   lcd_init();       //LCD Hasieratu
   lcd_gotoxy(6,1);   //Lehenengo lerroa,6.posizioa
   printf(lcd_putc,»RPM»);
   lcd_gotoxy(4,2);  //Bigarren lerroa, 5.posizioa
   printf(lcd_putc,»ms»);
   lcd_gotoxy(12,2);  //Bigarren lerroa, 11.posizioa
   printf(lcd_putc,»Gradu»);
   while(1)
   {
      while(getc()!=’Z’);  //Itxaron datuak jasotzeko marka jaso arte
      for(i=0;i<7;i++)
         datuak[i]=getc(); //Portu serietik datuak jaso
      for(i=0;i<7;i++)
         write_eeprom(i,datuak[i]); //Eeprom memorian jasotako datuak gorde
      //LCD RPM///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
      lcd_gotoxy(1,1);                 //Lehenengo lerroa,1.posizioa
      printf(lcd_putc,»%c»,datuak[0]);    //RPM; Milakoak
      printf(lcd_putc,»%c»,datuak[1]);    //RPM; Ehunekoak
      printf(lcd_putc,»00″);              //RPM; Hamarrekoak eta Batekoak
      //LCD ANGULO AVANCE///////////////////////////////////////////////////////////////////////////////////////////
      lcd_gotoxy(8,2);                 //Bigarren lerroa,8.posizioa
      printf(lcd_putc,»%c»,datuak[2]);    //Angulo Avance; Seinua +-
      printf(lcd_putc,»%c»,datuak[3]);    //Angulo Avance; Hamarrekoa
      printf(lcd_putc,»%c»,datuak[4]);    //Angulo Avance; Batekoa
      //LCD TIEMPO INYECCION///////////////////////////////////////////////////////////////////////////////////////
      lcd_gotoxy(1,2);                 //Bigarren lerroa, 1.posizioa
      printf(lcd_putc,»%c»,datuak[5]);    //Inyekzioa; Hamarrekoa
      printf(lcd_putc,»%c»,datuak[6]);    //Inyekzioa; Batekoa
   }//while(1) bukara
}//main() bukaera
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*********************************************************************************************
                VDO
Medidor masa de aire
**********************************************************************************************
output_high(PIN_c3);//1
output_low(PIN_c4);//0
delay_ms(5000);
output_low(PIN_c3);//0
output_low(PIN_c4);//0
delay_ms(5000);
output_low(PIN_c3);//0
output_high(PIN_c4);//1
delay_ms(5000);
output_high(PIN_c3);//1
output_high(PIN_c4);//1
***********************************************************************************************/
#include <16F876A.H>
#device ADC=10
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4M)
int16 a;
int1 b,c,d,e,f,g;
void main(void)
{
   setup_adc_ports(AN0);
   setup_adc(adc_clock_internal);
   set_adc_channel(0);
   while(1)
   {
      a=read_adc();
      b=input(PIN_B1);//0%
      c=input(PIN_B2);//punto muerto
      d=input(PIN_B3);//25%
      e=input(PIN_B4);//50%
      f=input(PIN_B5);//75%
      g=input(PIN_B6);//100%
      if(b==0)
      {
         output_low(PIN_c4);//guztiz itxi
         output_high(PIN_c3);
      }
      else if(c==0)
      {
         output_high(PIN_c4);//jetsi baina motorrak lagunduta
         output_high(PIN_c3);//punto muerto
      }
      else if(d==0)
      {
         if(a>637)//50%   380
         {
            output_high(PIN_c4);//Ireki
            output_low(PIN_c3);
         }
         else
         {
            output_high(PIN_c3);//jetsi baina motorrak lagunduta
            output_high(PIN_c4);
         }
      }
      else if(e==0)
      {
         if(a>515)//50%   380
         {
            output_high(PIN_c4);//Ireki
            output_low(PIN_c3);
         }
         else
         {
            output_high(PIN_c3);//jetsi baina motorrak lagunduta
            output_high(PIN_c4);
         }
      }
      else if(f==0)
      {
         if(a>392)//50%   380
         {
            output_high(PIN_c4);//Ireki
            output_low(PIN_c3);
         }
         else
         {
            output_high(PIN_c3);//jetsi baina motorrak lagunduta
            output_high(PIN_c4);
         }
      }
      else if(g==0)
      {
         if(a>392)//50%   380
         {
            output_high(PIN_c4);//Ireki
            output_low(PIN_c3);
         }
      }
   }
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 

Motor kontrola / Control de motor

Motor kontrola / Control de motor

Castellano:

Nuestro proyecto se trata de un motor de continua, en el que se puede  controlar su dirección y velocidad. Para ello hemos diseñado la placa del circuito en el Layout basándonos en el esquema hecho en el Capture. Consta de unos conectores (LED y interruptor de on/off, aumentar/disminuir velocidad e invertir la dirección) que irán conectados a los botones del panel de control del motor. El circuito se alimenta con 5V.
En el circuito impreso tenemos todos los componentes soldados para cada función, entre ellos están el PIC 16F876 que dirigirá todo el funcionamiento del motor teniendo en cuenta los botones que se pulsen y el driver L293 el cual nos ayudará a variar la velocidad y sentido del motor comparando los dos PWM que el PIC le mandara. El circuito esta alimentado en continua, pero gracias a las modificaciones del PWM conseguimos nuestro objetivo principal, que es variar la tensión que le llega al motor.

Euskara:

Gure proiektua motor baten kontrola lortzean datza. Panel baten bidez, motorraren abidadura eta norantza eman diezaiokegu. Hori lortzeko, bere zirkuituaren plaka diseinatu eta kontrol panela eraiki dugu.
Zirkuituan beharrezkoak diren konponenteak aukeratu eta ipini ditugu, hauen artean PIC16F876A eta L293B dira garrantzitsuenak. Bi hauek erabiliz eta PWM-a programatuz, motorraren abiadura kontrolatu ahal izango dugu pultsuen zabalera aldatuz.

 

.

HAUXE DA ERABILI DUGUN SOFTWAREA:

http://chopapp.com/#xw89p6gz

Como capturar una comunicación serie USART

Como capturar una comunicación serie USART

Para capturar una comunicación serie no hace falta nada más que un osciloscopio digital. El osciloscopio hay que conectarlo a una de las lineas de comunicación (RxD o TxD) y a masa (Gnd). En esta práctica se comunican dos microcontroladores entre si. En este caso son dos PICs pero se podría hacer lo mismo con cualquier otro microcontrolador como Arduino o el 8051.
.
.
En el video se puede ver como al mandar el dato 45 en hexadecimal (creo que es el F en Ascii) como es enviado ese dato. Esto se ha conseguido con un pequeño programa donde una y otra vez se envia el dato y un pequeño delay para que se vea más claro la información enviada.
.

MINISUMO

MINISUMO

 

Definición:

– Este proyecto es un robot cuyo objetivo es localizar al robot oponente, ir a por el y tirarlo del tatami.

– Para localizar al otro robot hemos utilizado los sensores CNY70 controlados por unos servo motores. Hemos utilizado el chip L293, según lo que detecten los sensores este integrado va ha hacer que los motores giren adelante o hacia atrás.

– Nuestro proyecto esta controlado por el PIC16F876.

– Hemos utilizado dos sensores para detectar al robot oponente, los GP2D12 que miden la distancia, así vamos ha poder atacar al robot oponente y echarlo del tatami.

 

 

 

 

#include <16F876A.H>
#device adc=10
#use delay(clock=20000000)
#fuses HS,NOWDT,NOPROTECT
//#include «lcd.c»
#define botoia_1 input(PIN_C6)
#define botoia_2 input(PIN_C7)
#define MI_1 PIN_C0
#define MI_2 PIN_C1
#define MD_1 PIN_C2
#define MD_2 PIN_C3
#define CNY_1 PIN_C4
#define CNY_2 PIN_C5void ezkerrera (void);
void eskubira (void);
void aurrera (void);
void atzera(void);
void sentsoreak (void);
void geldi (void);int16 toke_1, toke_2; //1 – ezkerra/**********************************************************************
EZKERRERA FUNTZIOA: Funtzio honetan sartzen bada, robotak ezkerrera
giratu behar du beste robota aurkitu arte. Aurkitzerakoan ezkerreko
funtziotik aterako da eta aurrera funtzian sartu beharko du.
**********************************************************************/
void ezkerrera (void)
{
output_high(MI_1); //motorI aurrera
output_low(MI_2);
output_high(MD_1); //motorD geldi egon
output_low(MD_2);
}

/*********************************************************************
EZKUBIRA FUNTZIOA: Funtzio honetan sartzen bada, robotak eskubira
giratu behar du beste robota aurkitu arte. Aurkitzerakoan eskubiko
funtziotik aterako da eta aurrera funtzian sartu beharko du.
*********************************************************************/
void eskubira (void)
{
output_low(MI_1); //motorI aurrera
output_high(MI_2);
output_low(MD_1); //motorD geldi egon
output_high(MD_2);   //motor_2_atzera geldi egon

}

/********************************************************************
AURRERA FUNTZIOA: Funtzio honetan sartzen bada, horrek esan nahi du
beste robota lokalizatu duela. Orduan gure minisumoak aurrera egingo du
bestea bultzatuz. Bestea bistaz galdu badu azkena galdu duen sensorea
dagoen lekuan(ezkerrean edo eskubian) norantza hori artuko du aurkitu arte.
********************************************************************/
void aurrera (void)
{
/*   output_high(MI_1); //motorI aurrera
output_low(MI_2);
output_low(MD_1); //motorD geldi egon
output_high(MD_2);   //motor_2_atzera geldi egon
*/
output_low(MI_1); //motorI aurrera
output_high(MI_2);
output_high(MD_1); //motorD geldi egon
output_low(MD_2);
}

/********************************************************************
ATZERA FUNTZIOA: Funtzio honetan sartzen bada, minisumoak tatamiko
zona txuria ikutu duela esan nahi du eta atzera joango da tatamitik ez
ateratzeko.
********************************************************************/
void atzera (void)
{
/*   output_low(MI_1); //motorI aurrera
output_high(MI_2);
output_high(MD_1); //motorD geldi egon
output_low(MD_2);
*/
output_high(MI_1); //motorI aurrera
output_low(MI_2);
output_low(MD_1); //motorD geldi egon
output_high(MD_2);   //motor_2_atzera geldi egon
}

/*********************************************************************
GELDI FUNTZIOA: Funtzio honetan sartzen bada, robotak geldirik egon
beharko du, 5 segundu pasa arte. Funtzio hau robota piztu eta jarraian
sartuko da.
*********************************************************************/
void geldi (void)
{
output_low(MI_1); //motorI aurrera
output_low(MI_2);
output_low(MD_1); //motorD geldi egon
output_low(MD_2);
}
/*********************************************************************
FUNTZIO NAGUSIA:
*********************************************************************/
void main (void)
{
int1 t1=0,t2=0;   //gogoratzeko sentsoreen azken detekzioa
setup_adc(ADC_CLOCK_INTERNAL);
setup_adc_ports (AN0_AN1_AN3);//Configura el PIN_A0 en analogico
//   set_rtcc(0);

geldi();
delay_ms(5000);   //5 segundu itxaron behar du zerbait egin baino lehen
if(botoia_1==1)
ezkerrera();   //ezkerrera funtziora joan
else
eskubira();    //eskubira funtziora joan

while(1)
{
set_adc_channel(0);//Especifica que utilizara el canal A0
delay_us(20);
toke_1=read_adc();
delay_us(20);
set_adc_channel(1);//Especifica que utilizara el canal A1
delay_us(20);
toke_2=read_adc();

if(((toke_1>80)&&(toke_2>80))&&((input(CNY_1)==0)&&(input(CNY_2)==0))) //biak detektatu
{
aurrera();  // Aurrera funtzioan sartuko da.
t1=1; t2=1;
}
else if(((toke_1>80)&&(toke_2<80))&&((input(CNY_1)==0)&&(input(CNY_2)==0)))
{
ezkerrera();   // Ezkerrera funtzioan sartuko da.
t1=1; t2=0;
}
else if(((toke_1<80)&&(toke_2>80))&&((input(CNY_1)==0)&&(input(CNY_2)==0)))
{
eskubira(); // Eskubira funtzioan sartuko da.
t1=0; t2=1;
}

else if(((toke_1<80)&&(toke_2<80))&&((input(CNY_1)==0)&&(input(CNY_2)==0)))
{
ezkerrera();   // Ezkerrera funtzioan sartuko da.
}
/*         if((t1==1)&&(t2==0))
ezkerrera();   // Ezkerrera funtzioan sartuko da.
else if((t1==0)&&(t2==1))
eskubira();    // Eskubira funtzioan sartuko da.
}
*/
else if((input(CNY_1)==1)||(input(CNY_2)==1))
atzera();
}
}

Sigue Lineas

Sigue Lineas

Este ingenio electrónico es capaz de seguir una linea negra de determinadas proporciones sobre un campo blanco de forma autonoma, sin control externo. Los sensores que lo equipan y que ven la linea, determinan por medio de la programación del PIC 16F876A qué movimientos deben realizar los motores para alcanzar su objetivo. En función de la programación puede seguir una ruta lineal con curvas múltiples o un circuito determinado con cruces a ambos lados.

 

 

 

/***********************************************************************
sabe diferenciar mas o menos las marcas de direccion pero hay situaciones como la T que no sabe ni lo que tiene que hacer PIN_B6 eten 2 a 0 en ON a 1 en OFF PIN_B7 eten 1 a 0 en ON a 1 en OFF PIN_A5 Enable MD martxa/paro PIN_C0 Enable MI martxa/paro PIN_C1 PWM2 para el motor IZDA PIN_C2 PWM1 para el motor DCHA PIN_C7 MI zentzua kontrolatzeko 0 aurrera, 1 atzera PIN_C6 MD zentzua kontrolatzeko 0 aurrera, 1 atzera *********************************************************************/
#include <16f876A.h>
#use delay(clock=20000000)
#fuses NOPROTECT,NOWDT,HS,NOPUT,NOPROTECT,BROWNOUT
#fuses NOCPD,NOWRT,NODEBUG#use fast_io(A)
#use fast_io(B)
#use fast_io(C)#define vau1 40
#define vau2 50
#define vau3 60
#define vau4 70
#define vau5 80
#define vau6 90
#define vau7 100
#define vau8 110
#define vau9 120#define vat1 85
#define vat2 75
#define vat3 65
#define vat4 55
#define vat5 45
#define vat6 35
#define vat7 25
#define vat8 15
#define vat9 05#define S1 input(PIN_B0)
#define S2 input(PIN_B1)
#define S3 input(PIN_B2)
#define S4 input(PIN_B3)
#define S5 input(PIN_B4)
#define S6 input(PIN_B5)
#define S7 input(PIN_B6)
#define S8 input(PIN_B7)

#define MD_ON output_high(PIN_C0) //Motorra I martxan
#define MD_OFF output_low(PIN_C0) //Motorra I geldirik
#define MI_ON output_high(PIN_A5) //Motorra D martxan
#define MI_OFF output_low(PIN_A5) //Motorra D geldirik
#define MI_AUR output_low(PIN_C7) //Motorra ezkerra aurrera
#define MI_ATZ output_high(PIN_C7) //Motorra ezkerra atzera
#define MD_AUR output_low(PIN_C6) //Motorra eskubia aurrera
#define MD_ATZ output_high(PIN_C6) //Motorra eskubia atzera

#define N 1
#define B 0

int8 duty;

/*******************************************************************
Aurrera
*********************************************************************/
void aurrera(void)
{
MI_AUR; set_pwm2_duty(duty);
MD_AUR; set_pwm1_duty(duty);
}

/*******************************************************************
giro Ezkerrera (suave)
********************************************************************/
void gir_ezk(void)
{
MD_AUR; set_pwm1_duty(vau7);
MI_AUR; set_pwm2_duty(0);            // MI paro rapido (0,0)
}

/*******************************************************************
giro Eskubira (suave)
*********************************************************************/
void gir_esk(void)
{
MI_AUR; set_pwm2_duty(vau7);
MD_AUR; set_pwm1_duty(0);         // MD paro rapido (0,0)
}

/*******************************************************************
Errotazio Ezkerrera (brusco)
********************************************************************/
void rot_ezk(void)
{
MD_AUR; MI_ATZ;
set_pwm1_duty(vau9);
set_pwm2_duty(vat7);
}

/*******************************************************************
Errotazioa Eskubira (brusco)
*********************************************************************/
void rot_esk(void)
{
MD_ATZ; MI_AUR;
set_pwm1_duty(vat7);
set_pwm2_duty(vau9);
}

/*******************************************************************
Paroa
*********************************************************************/
void paro(void)
{
MD_AUR; set_pwm1_duty(0);            // MD paro rapido (0,0)
MI_AUR; set_pwm2_duty(0);             // MI paro rapido (0,0)
}

/*******************************************************************
Eskubira
*********************************************************************/
void main()
{
int1 ezes=0; //hasi eskubitik
// int1 s0,s1,s2,s3,s4,s5,s6,s7,s8,s9;

setup_adc_ports(NO_ANALOGS);
setup_timer_2(T2_DIV_BY_16,124,1);
setup_ccp1(CCP_PWM);
setup_ccp2(CCP_PWM);

set_tris_a(0b00011111); //A5 irteera
set_tris_b(0XFF);
set_tris_c(0);

MD_ON;
MI_ON;
paro();

switch(input_a()&0b00000011)
{
case 0x00 : duty= 40;
break;
case 0x01 : duty= 65;
break;
case 0x02 : duty= 80;
break;
case 0x03 : duty= 120;
break;
}

while(ezes==0) //dena eskubitik
{
if((S1==N)&&(S2==N)&&(S4==B))
{
aurrera();
}
else if((S1==N)&&(S2==B)&&(S4==B)) //rectifica a la izq
{
gir_ezk();
}
else if((S1==B)&&(S2==N)&&(S4==B)) //rectifica a a dcha
{
gir_esk();
}
}
}//main bukaera