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.
Para poder controla todos estos parametros tendremos una señal situada en el motor.
.
.
.
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);
}
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////