Hola a todos, me encuentro desarrollando el software para el Arduino Uno, para el control de algunas variables de un motor de 4 tiempos para el Control del motor de un Auto y la cantidad de gas entredada por un equipo de Gas Natural Comprimido de 2da Generación.
Tomo información del sensor inductivo posición del cigüeñal (ckp) para desfasar la señal y así desfasar la chispa de las bujías. Tomo la señal del sensor de posicion del acelerador (TPS) e información de la sonda Lambda (Medición de Oxigeno en el escape) para controlar la entrada de gas al motor.
Los sensores de referencia son los siguientes:
Sensor CKP:
https://mecanicabasicacr.com/osciloscopio/forma-de-onda-de-un-sensor-de-posicion-de-ciguenal-ckp.html
https://forum.arduino.cc/index.php?topic=567187.0
Sensor TPS:
https://www.autodaewoospark.com/sensor-TPS.php
Sensor de O2:
http://www.aficionadosalamecanica.net/sonda-lambda.htm
El código es el siguiente:
const int salida = 10; //a la ecu
const int interrupcion = 2; //sensor ckp
const int sensorTps = A1; //sensor acelerador
const int sensorLambda = A0; // medicion de la sonda lambda
const int actuadorMPP = 9
//variables
int medicionTps = 0;
int medicionLambda = 0;
int tiempoInicial=0;
int tiempoBajo=0;
int tiempoAnterior=0
int contadorBajos=0;
int contadorAltos=0;
int rpmRelenti=900;
int encendido=0;
int lambda=0;
long ciclos=0;
int retardoVariable=0;
dientes
contador
//referencias
int lambdaMin=500;
int lambdaMax=1500;
int tpsMin=500;
int tpsMax=5000;
int valorActuadorMPP=125;
int valorActuadorMPPMin=10;
int rpmVector[50];
int mapaRevoluciones[] = { 15 , 15 , 15 , 15 , 15 , 15 , 15 , 15 , 15 , 15 , 15 , 15 , 15 , 15 }
// 500 1000 1500 2000 2500 3000 3500 4000 4500 5000 5500 6000 6500 7000
int mapaLambda[] = { 125 , 125 , 125 , 125 , 125 , 125 , 125 , 125 , 125 , 125 , 125 , 125 , 125 , 125 }
// 500 1000 1500 2000 2500 3000 3500 4000 4500 5000 5500 6000 6500 7000
/************************************************************************************************************************************************/
void setup()
{
pinMode(salida, OUTPUT);
pinMode(interrupcion, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interrupcion),interrupcionFlancoDecendente, FALLING);//siempre inicio contando el bajo
retardoVariable=retardo(0);
}
/************************************************************************************************************************************************/
void loop()
{
//calculo las Rpms del motor
if(dientes) //se realiza si ya se determinadron la cantidad de dientes
if(contador==dientes) //se realiza en cada vuelta
if(tiempoBajo<tiempoAnterior*1,15) //solo calculo rpm para los pulsos normales
{
calculoRpm();
retardoVariable=retardo(1);
}
if(encendido) //si el gnc esta activado actuo sobre la sonda lambda
controlLambda();
}
/************************************************************************************************************************************************/
interrupcionFlancoDecendente //copio señal de entrada hasta que puedo calcular ancho de dientes y rpms
{
delayMicroseconds(retardoVariable);
digitalWrite(salida,LOW);
tiempoInicial=micros();
tiempoAlto=tiempoInicial-tiempoBajo;
attachInterrupt(digitalPinToInterrupt(interrupcion),interrupcionFlancoAscendente, RISING);
}
interrupcionFlancoAscendente
{
delayMicroseconds(retardoVariable);
digitalWrite(salida,HIGH);
tiempoBajo=micros()-tiempoInicial;
tiempoAnterior=tiempoBajo;
cuentaDientes();
attachInterrupt(digitalPinToInterrupt(interrupcion),interrupcionFlancoDecendente, FALLING);
}
/************************************************************************************************************************************************/
int retardo(int activado) //calcula retardo en funcion de las rpm y el ancho del pulso, devuelve uS
{
if(activado)
{
if(sensorTps=0)
return 15;
else
{
avanceIntermedio=interpolacion(rpm,rpm/500,mapaRevoluciones[rpmInf],rpm/500+1,mapaRevoluciones[rpmSup]);
return round(avanceIntermedio);
}
}
else
return 0;
}
/************************************************************************************************************************************************/
//Control lambda
void controlLambda(void)
{
medicionLambda = analogRead(sensorLambda);
medicionLambdaMap = map(medicionLambda, lambdaMin, lambdaMax, 0, 255);
medicionTps = analogRead(sensorTps);
medicionTps = map(medicionTps, TpsMin, TpsMax, 0, 255);
//500 600 700 800 900 1000 1100 1200 1300 1400 1500
// 0 26 52 78 104 130 156 182 208 234 255
// 0 1 2 3 4 5 6 7 8 9 10
controlLambdaRef();
if(medicionLambdaMap < lambdaRef) // establezco rangos de velocidad de actuacion
{
if(medicionLambdaMap < lambdaRef*2/10 && medicionLambdaMap => lambdaRef*0/10 )
valorActuadorMPP=funcionActuador(valorActuadorMPP,20);
if(medicionLambdaMap < lambdaRef*4/10 && medicionLambdaMap => lambdaRef*2/10 )
valorActuadorMPP=funcionActuador(valorActuadorMPP,10);
if(medicionLambdaMap < lambdaRef*5/10 && medicionLambdaMap => lambdaRef*4/10 )
valorActuadorMPP=funcionActuador(valorActuadorMPP,1);
}
else
{
if(medicionLambdaMap < lambdaRef*10/10 && medicionLambdaMap => lambdaRef*7/10 )
valorActuadorMPP=funcionActuador(valorActuadorMPP,20);
if(medicionLambdaMap < lambdaRef*7/10 && medicionLambdaMap => lambdaRef*6/10 )
valorActuadorMPP=funcionActuador(valorActuadorMPP,10);
if(medicionLambdaMap < lambdaRef*6/10 && medicionLambdaMap => lambdaRef*5/10 )
valorActuadorMPP=funcionActuador(valorActuadorMPP,1);
}
if(medicionTps>=TpsMax*0.95) //apertura total con el pedal a fondo
valorActuadorMPP=valorActuadorMPPMax;
if(medicionTps<=TpsMmin) //cierre cuando se saca el pie del acelerador
valorActuadorMPP=valorActuadorMPPMin;
analogWrite(actuadorMPP, valorActuadorMPP);
}
void controlLambdaRef(void)
{
lambdaRef = =interpolacion(rpm,rpm/500,mapaLambda[rpm/500],rpm/500+1,mapaLambda[rpm/500+1])
}
int funcionActuador(int valorinicial,int incremento)
{
return valorinicial+incremento;
}
/************************************************************************************************************************************************/
void calculoRpm(void)
{
periodo=(2*(dientes+2)*tiempoAlto); //periodo en uS de 1 vuelta es igual a 58 dientes/58 huecos + 4 huecos
rpm=60/(periodo/1000000); //calculo sobre tiempo alto para evitar los huecos dobles
}
/************************************************************************************************************************************************/
//funcion interpolacion
int interpolacion(int x,int x1,int y1,int x2,int y2)
{
float y;
y=(x-x1)(y2-y1)/(x2-x1)+y1;
return round(y);
}
/************************************************************************************************************************************************/
int retardo(int grados)
{
long retardoX;
retardoX=tiempoAlto*2*grados/360;
if(retardoX<=3) //minima resolucion de delaymicros() sin error
retardoX=3;
return round(retardoX);
}
/************************************************************************************************************************************************/
void cuentaDientes(void)
{
if(tiempoAnterior!=0)
{
if(tiempoBajo>tiempoanterior*1,75)
{
iniciarCuenta=!iniciarCuenta;
dientes=contadorAltos;
}
}
if(iniciarcuenta)
if(dientes!=contadorAltos
contadorAltos++;
else
contadorAltos=0;
}
Espero de su colaboración para mejorar el código dado que esto es solo el primer borrador.
Saludos,
Leonardo
PD: Tengo mi proyecto en Github: https://github.com/leogbar/ControlGnc
Variables