Emulador de ECU para Jeep con Arduino

Estoy realizando un emulador de una ECU para una jeep Wrangler y tengo fallas al realizar el disparo.
Pienso yo en un retardo el cual no me permite disparar a tiempo para energizar la bobina.

Adjunto un código que modifiqué para realizar el proyecto.
PHP:
#include <FreqCount.h>
int inyector = 10,n;
volatile unsigned long cont_ckp, cont_cmp;

   static float rpm_actuales; 
void setup() {
  attachInterrupt(1, ckp, RISING);
  attachInterrupt(0, cmp, FALLING);
  pinMode(inyector, OUTPUT);
  Serial.begin(9600);
     FreqCount.begin(1000);
  cont_cmp==0;
}

void ckp()
{
  cont_cmp = 0;
}
void cmp()
{
  cont_cmp++;

  }

void loop() {
  //delay(200);
if((cont_cmp==4))
{
 // delay (250);
   analogWrite(inyector, 255);
delay(1200);
analogWrite(inyector, 0);

}
if((cont_cmp==8))
{
  //  delay (250);
   analogWrite(inyector, 255);
delay(1200);
analogWrite(inyector, 0);

}
if((cont_cmp==12))
{
  //delay (250);
   analogWrite(inyector, 255);
delay(1200);
analogWrite(inyector, 0);

}
if((cont_cmp==16))
{
   // delay (250);
   analogWrite(inyector, 255);
delay(1200);
analogWrite(inyector, 0);

}
  Serial.println(cont_cmp);    
}
 
Última edición por un moderador:
Mmmm retardos. Mis favoritos. ¿Por donde empiezo?

Bueno, empiezo por el resto.
El título "Una consulta, tengo problemas con un proyecto que estoy realizando." es lo mismo que no decir nada, debiste de usar un título descriptivo.
Dar datos siempre está bien; micro que usas, lenguaje y versión del compilador, diagrama del conexionado...
No por nada, es que tengo la bola de cristal en el taller porque le están cambiando el líquido de la trasnmisión y ahora mismo se me hace complicado adivinar los detalles.
¿El delay está en mili segundos? Si la respuesta es si ¿Crees que un motor puede estar parado segundo y pico?
¿Por que gobiernas los inyectores con señales analógicas?
Creo que unos comentarios en el código estaría bien; solo tu sabes que es lo que estás haciendo.

Va, la suelto:
Entierra los delays bien hondo en tu cerebro, le pones un metro de hormigón mental encima y no los uses mas. Usa timers e interrupciones que se inventaron para algo y no revientan cada código que tocan. Una ECU de un motor es bastante crítica en cuanto a los tiempos y usar delays es el camino de la perdición, te lo dice uno que nuna vez programó una ECU (sin delays, claro)
 
Propongo que Scooter responda a todos los hilos en los que hay delay() con una respuesta acorde a su gusto en FORMA DE CÓDIGO que resuelva la cuestión del tema, y no en FORMA DE REPRIMENDA.

Decir que odias los delay() está bien, y yo lo comparto, pero para un novato, no le sirve de nada si no ve un ejemplo de lo que le estás contando.

Al menos... ponle un enlace a un ejemplo de lo que le estás proponiendo.
 
Hola
Propongo que Scooter responda a todos los hilos en los que hay delay() con una respuesta acorde a su gusto en FORMA DE CÓDIGO que resuelva la cuestión del tema, y no en FORMA DE REPRIMENDA.

Decir que odias los delay() está bien, y yo lo comparto, pero para un novato, no le sirve de nada si no ve un ejemplo de lo que le estás contando.

Al menos... ponle un enlace a un ejemplo de lo que le estás proponiendo.
No estoy de acuerdo con lo que planteas ., ni como lo planteas​
Ya an pasado 24Hs (o mas) ., ni hay esquema ., ni compilacion completa ., mas alla del DELAY"s o no​
Pero si te parece correcto en investigar y proporcionar ayuda ., si el interesado no pone de su parte ¿¿¿¿ porque tenemos que hacer su trabajo ???​
poner ejemplos y/o links extrenos ., significa que por un lado yo tengo que buscar he investigar​
Si el intresado no lo hace ¿¿¿¿ porque lo tengo que hacer yo ???​
No me molesta ., ni me niego a compartir lo que se ., porque en definitiva ., no me lo voy a llevar al "cajon" el dia que me muera​
Esta perfecta y correcta ., la respuesta de SCOOTER ., pero si fue mala la tuya porque objetaste a SCOOTER
Pero de tu parte ., no ayudaste al consultante con ejemplos ., le pedis a otros lo que vos no haces ., !!! lindo ejemplo ¡¡¡ hay que criticar menos y aportar mas​
 
Tuve que hacer algunas cosas, recientemente pude conectarme y ver.
Gracias por las respuestas.
Acá envío el código que corregí.
Soy novato en programación, así que disculpas por los errores.
PHP:
int inyector = 12, tiempoig = 6;//Declaramos inyector al pin numero 12, y tiempoig es el tiempo de ignicion en milisegundos
byte temp = 0;//es una variable que utilizo para detectar si esta habilitado el temporizador
unsigned long tiempoAnterior = 0;// variable para guardar el valor de millis
volatile unsigned long cont_ckp, cont_cmp;// ambos son contadores para sincronizar los sensores 
void setup() {
  attachInterrupt(1, ckp, RISING);// declaramos la interrupcion cada cambio a nivel alto
  attachInterrupt(0, cmp, FALLING);// declaramos la interrupcion cada cambio a nivel bajo
  pinMode(inyector, OUTPUT);//declaramos inyector como salida
  Serial.begin(9600);    
  cont_cmp==0;//iniciamos el contador en 0
  cont_ckp==0;//iniciamos el contador en 0
}

void ckp()
{
  cont_cmp = 0;//reiniciamos el contador
}
void cmp()
{
  cont_cmp++;//incrementamos el contador cada que se habilita la interrupcion

  }

void loop() {
if((cont_cmp==4))//si el contador es igual a 4
{
tiempoAnterior=millis();//iniciamos tiempoanterior
digitalWrite(inyector, HIGH);//habilitamos el pin12 en estado alto
temp = 1;//colocamos en 1 para saber que el temporizador esta activo


}
if((cont_cmp==8))//si el contador es igual a 8
{
tiempoAnterior=millis();//iniciamos tiempoanterior
digitalWrite(inyector, HIGH);//habilitamos el pin12 en estado alto
temp = 1;//colocamos en 1 para saber que el temporizador esta activo



}
if((cont_cmp==12))//si el contador es igual a 12
{
tiempoAnterior=millis();//iniciamos tiempoanterior
digitalWrite(inyector, HIGH);//habilitamos el pin12 en estado alto
temp = 1;//colocamos en 1 para saber que el temporizador esta activo


}
if((cont_cmp==16))//si el contador es igual a 16
{

tiempoAnterior=millis();//iniciamos tiempoanterior
digitalWrite(inyector, HIGH);//habilitamos el pin12 en estado alto
temp = 1;//colocamos en 1 para saber que el temporizador esta activo


}
  if((tiempoAnterior>tiempoig)&&temp==1){  //si ha transcurrido el periodo programado
      digitalWrite(inyector,LOW);  //apagamos el pin12
      temp = 0;  //y desactivo el temporizador
      tiempoAnterior =0; //igualamos el contador a 0 para el proximo disparo
  }
  Serial.println(cont_cmp);    
}
 
Última edición por un moderador:
Hola
No estoy de acuerdo con lo que planteas ., ni como lo planteas​
Ya an pasado 24Hs (o mas) ., ni hay esquema ., ni compilacion completa ., mas alla del DELAY"s o no​
Pero si te parece correcto en investigar y proporcionar ayuda ., si el interesado no pone de su parte ¿¿¿¿ porque tenemos que hacer su trabajo ???​
poner ejemplos y/o links extrenos ., significa que por un lado yo tengo que buscar he investigar​
Si el intresado no lo hace ¿¿¿¿ porque lo tengo que hacer yo ???​
No me molesta ., ni me niego a compartir lo que se ., porque en definitiva ., no me lo voy a llevar al "cajon" el dia que me muera​
Esta perfecta y correcta ., la respuesta de SCOOTER ., pero si fue mala la tuya porque objetaste a SCOOTER
Pero de tu parte ., no ayudaste al consultante con ejemplos ., le pedis a otros lo que vos no haces ., !!! lindo ejemplo ¡¡¡ hay que criticar menos y aportar mas​

Hola locodelafonola, yo si estoy de acuerdo con lo que dice JoaquinFerrero, tambien con parte de lo que dices tu y parte de lo que dice scooter. Pero creo que siempre pecamos un poco de "soberbia", cuando respondemos a un novato. Al fin y al cabo si viene aqui a preguntar, salvo los casos concretos que todos sabemos, es porque no sabe hacerlo solo.
De todos modos tampoco puedes acusar a alguien de que no respondio en 24 horas, la gente tiene que trabajar y hacer su vida aparte de participar en el foro y por otro lado podria ser que como dice JaquinFerrero, no supiese solucionar lo de los timer o interrupciones y este estudiandolo.
Resumiendo, esto es un foro, no es un cuartel. Pienso que debemos ser un poco mas humildes y recordar que hace unos años, nosotros tambien preguntabamos y nos gustaban las respuestas que nos ayudaban y no tanto las que nos reprendian.
Finalmente respecto a comentar y no dar las soluciones que proponemos, ¿no has pensado que quizas podamos conocer el concepto, pero no saber desarrollarlo?. En mi caso asi es.

Saludos.
 
Hay que diferenciar entre un principiante, donde todo es nuevo y cuesta aprender de golpe cosas complicadas.
Un ejemplo simple y estúpido por el cual pasamos todos.
En el escuela nos enseñaron la regla de tres y era la única forma de resolver ciertas cosas, pero cuando fuimos más adelante en nuestros estudios descubrimos las proporciones y nunca más usamos la regla de tres.

Retar a un principiante por utilizar la regla de tres y no utilizar las proporciones es lo mismo.

Para que se centre en la parte importante al comienzo el uso de delay no implica ningún problema,
Es la misma cuestión si utilizo un 555 o un micro para un timer, hay situaciones en la cual un 555 resuelve las cosas de una manera más simple y eficiente y más barata que un micro, pero hay otras en la que no se puede pensar en otra cosa que no sea un micro.

Por otro lado muchos gracias a arduino se inician en la programación personas que jamás en su vida utilizaron un lenguaje de programación, y deben aprender como funciona un micro y ala vez aprender C

Hay muchos que trabajaron Con "C" y lo conocen al dedillo, por lo tanto el C aplicado a micros es un juego de niños, pero es un mundo para quien no lo conoce.

aprender que es una estructura, que es una función, que son la variables, porque algunas se declaran y otras no, que es un bucle, que es un anidamiento, es menester que aprendan paso a paso y que de momento utilicen un delay, y que a medida que avancen y vayan concociendo más el lenguaje y la estructura de un micro vayan avanzando en los métodos de programación.
Cuantos de ustedes que critican en los primeros meses metieron una línea de asm en medio todo el código para optimizarlo? hay muchos que jamas han puesto una línea de código en asm....

Por su parte los que empezaron programando los primeros micros lo hacian en asembler y con nemónicos en hexadecimal, las placas de desarrollo del 6800 y posteriores se programban así, otra que entorno de desarrollo. Obviamente estos conocen más que nadie, porque trabajaron desde las tripas de los micros, personas que se sabían el C como el padre nuestro, pero ni pensar que se aplicaría a micros, hoy en día utilizan lo mejor de cada uno, verdaderos monstruos de la programación, pero estos tipos que saben tanto jamás lo vi tratar a un principiante como lo ha echo Scooter y menos que lo apoyara como lo ha echo loco de la fonola, cuando han corregido a alguién lo hacen con gran respeto y le muestran como deberia ser, con ejemplos archiprácticos que le serviran para toda la vida.

Por lo tanto una cosa es saber mucho y otra tener la capacidad de enseñar.

Por lo tanto (de nuevo) si sabes mucho y no sabes enseñar, no hables, guarda tu conocimiento para ti mismo.
De otro modo la crítica en vez de ser constructiva es destructiva.
Por eso estoy en todo de acuerdo con lo que propone Joaquin, si sabes tanto demuestralo y si no tienes ganas no crítiques
 
Sigo pensando que faltan datos para interpretar el código.
Esquemas, comentarios en el código, que indique que procesador es etc



 
Seria bueno saber que es lo que realmente debe hacer el programa; asi seria mas fácil ayudar a corregir el actual o hacer otro. No entiendo si los delay son tan malos, ¿por que los lenguajes de programación los incluyen?.
:unsure:
 
PHP:
  cont_cmp==0;//iniciamos el contador en 0
  cont_ckp==0;//iniciamos el contador en 0
En realidad... los estás inicializando a 1... Has puesto '==' en lugar de '='.

Además, no estás usando cont_ckp en ninguna otra parte del programa.

En el resto del programa... estás usando la función millis(), que devuelve el número de milisegundos que el microcontrolador lleva encendido. Eso quiere decir que se trata de un valor que siempre está creciendo, por lo que la última condición (tiempoAnterior > tiempoig) siempre se cumplirá, pasados los primeros 6 ms.

Si lo que quieres es saber el tiempo que ha pasado el pin 12 en activo (temp == 1) entonces necesitas una variable más que marque el tiempo de inicio de ese periodo. tiempoAnterior hace justo esa labor. El problema es que la condición no es correcta. Debería ser algo así:

(millis() - tiempoAnterior > tiempoig)

De esa manera estás calculando el tiempo que ha pasado desde que inicializaste tiempoAnterior. Otro ejemplo: parpadeo de un LED sin usar delay()

Otro detalle: el envío de información por puerto serie es muy lento. Seguro que mucho más que los 6 ms de periodo de disparo que quieres en tu programa, así que esas instrucciones afectan al funcionamiento.

Recuerda también que las interrupciones 0 y 1 deben ir a los pines 2 y 3. Lo recomendable es usar la función de soporte digitalPinToInterrupt().

Sería algo así (no probado):
PHP:
#include <FreqCount.h>

int inyector = 12;                            // declaramos inyector al pin número 12
int tiempoig = 6;                             // tiempo de ignición en milisegundos

byte temp = 0;                                // detectar si está habilitado el temporizador
unsigned long tiempoAnterior = 0;             // guardar el valor de millis
volatile unsigned long cont_ckp, cont_cmp;    // contadores para sincronizar los sensores


void ckp() {                                  // interrupción en pin 3
    cont_cmp = 0;                             // reiniciamos el contador
}

void cmp() {                                  // interrupción en pin 2
    cont_cmp++;                               // incrementamos el contador
}

void setup() {
    attachInterrupt(digitalPinToInterrupt(3), ckp, RISING);      // interrupción en cambio a nivel alto
    attachInterrupt(digitalPinToInterrupt(2), cmp, FALLING);     // interrupción en cambio a nivel bajo

    pinMode(inyector, OUTPUT);                // declaramos inyector como salida

    //Serial.begin(9600);

    cont_cmp = 0;                             // iniciamos el contador en 0
    //cont_ckp = 0;                             // iniciamos el contador en 0
}

void activa_inyector() {
        tiempoAnterior = millis();            // inicializamos tiempoAnterior
        digitalWrite(inyector, HIGH);         // establecemos el pin12 en estado alto
        temp = 1;                             // el temporizador está activo
}

void desactiva_inyector() {
        tiempoAnterior = 0;                  // igualamos el contador a 0 para el próximo disparo
        digitalWrite(inyector,LOW);          // apagamos el pin12
        temp = 0;                            // y desactivo el temporizador
}

void loop() {
    if (cont_cmp == 4
    ||  cont_cmp == 8
    ||  cont_cmp == 12
    ||  cont_cmp == 16
    ) {                                      // si el contador es igual a 4, 8, 12 o 16
        activa_inyector();
    }

    // si ha transcurrido el periodo programado
    if (temp == 1  &&  (millis() - tiempoAnterior > tiempoig)) {
        desactiva_inyector();
    }

    //Serial.println(cont_cmp);
}
Como ejercicio para casa: ¿por qué he colocado temp == 1 en el lado izquierdo de la última condición?

Sigo pensando que faltan datos para interpretar el código:
Esquemas, comentarios en el código, qué procesador es, etc.
Lo ha dicho en el primer mensaje: es un Arduino Uno, por lo que el procesador es un ATmega328P a 16 Mhz.
 
Los delays me nublaron la visión, jajaja

Mira la librería flexitimer que permite usar con facilidad los timers. Te simplificará bastante el código.

La decisión de empezar a inyectar yo la pondría en la interrupción; ahora mismo empiezas varias veces a inyectar y el tiempo no será exacto.

Para desconectar, mejor con timers porque con los milis del sistema tienes un error de +-1ms osea que lo mismo inyecta 6 que 7 ms según pilles los tics del sistema. Eso hará que el motor no vaya "redondo"

Parece que solo estás controlando la inyección; en la inyección indirecta es poco crítico cuando se inyecta la gasolina; ya lo absorberá el motor cuando entre en admisión. Lo que si que es muy crítico es el encendido.

Te falta algo mas; necesitas saber que hace el acelerador o la mariposa porque cuando se da un acelerón de golpe las uces de verdad enriquecen la mezcla durante un par de vueltas del motor.; de lo contrario entra demasiado aire de golpe con muy poco combustible y puede no encender por ser demasiado pobre.

Me parece que no controlas el encendido pero te comento que, descubrí que el motor arranca en frío muchísimo mejor si atrasas el encendido bastante; unos 30 o 45º, en seguida lo tienes que volver a ajustar porque si no lo haces irá mal y echará fuego por el escape. Bueno, eso era con etanol, no con gasolina, y parece que no hacía bien la mezcla y al esperar un poco el hecho es que arrancaba al primer pistonazo al hacer una cierta depresión y vaporizar bien el etanol en frío. Eso lo controlaba con las rpm, en cuanto subía de vueltas ponía el encendido en el punto muerto superior.

Yo haría esto en pseudocódigo
Código:
void cmp() {                                  // interrupción en pin 2
    cont_cmp++;                               // incrementamos el contador
si cuenta == a, b, c o d entonces
activa inyector
empieza timer
}

rutina del timer:
{
corta inyector
}

Ahora ya tienes todo el tiempo para todo lo demás; contar las rpm leer la mariposa etc
 
Última edición:
Gracias por la ayuda, vere de probarlo asi, pienso yo que puso la variable temp al principio para primero verificar si el temporizador esta activo. no estoy seguro de eso.
El serial utilizaba para comprobar el contador ya que el sensor me envia 4 picos de 5 voltios separados 3ms cada uno cada 180 grados de giro de el arbol de levas del motor, como tenia problemas al momento de disparar coloque el serial para verificar si estaba realizando la cuenta o se saltaba alguna interrupcion, Gracias por la ayuda



Los delays me nublaron la visión, jajaja

Mira la librería flexitimer que permite usar con facilidad los timers. Te simplificará bastante el código.

La decisión de empezar a inyectar yo la pondría en la interrupción; ahora mismo empiezas varias veces a inyectar y el tiempo no será exacto.

Para desconectar, mejor con timers porque con los milis del sistema tienes un error de +-1ms osea que lo mismo inyecta 6 que 7 ms según pilles los tics del sistema. Eso hará que el motor no vaya "redondo"

Parece que solo estás controlando la inyección; en la inyección indirecta es poco crítico cuando se inyecta la gasolina; ya lo absorberá el motor cuando entre en admisión. Lo que si que es muy crítico es el encendido.

Te falta algo mas; necesitas saber que hace el acelerador o la mariposa porque cuando se da un acelerón de golpe las uces de verdad enriquecen la mezcla durante un par de vueltas del motor.; de lo contrario entra demasiado aire de golpe con muy poco combustible y puede no encender por ser demasiado pobre.

Me parece que no controlas el encendido pero te comento que, descubrí que el motor arranca en frío muchísimo mejor si atrasas el encendido bastante; unos 30 o 45º, en seguida lo tienes que volver a ajustar porque si no lo haces irá mal y echará fuego por el escape. Bueno, eso era con etanol, no con gasolina, y parece que no hacía bien la mezcla y al esperar un poco el hecho es que arrancaba al primer pistonazo al hacer una cierta depresión y vaporizar bien el etanol en frío. Eso lo controlaba con las rpm, en cuanto subía de vueltas ponía el encendido en el punto muerto superior.

Yo haría esto en pseudocódigo
Código:
void cmp() {                                  // interrupción en pin 2
    cont_cmp++;                               // incrementamos el contador
si cuenta == a, b, c o d entonces
activa inyector
empieza timer
}

rutina del timer:
{
corta inyector
}

Ahora ya tienes todo el tiempo para todo lo demás; contar las rpm leer la mariposa etc

Gracias por la ayuda, si yo se que en inyeccion se que el tiempo de inyeccion debe variar segun a los valores de cada sensor del vehiculo, estoy trabajando con 2 arduinos uno me realiza el calculo de el tiempo de inyeccion y lo envia por i2c y el otro recibe y usa ese tiempo para la inyeccion, el problema es que no podia sincronizar bien el disparo por eso quite el valor que me enviaban por i2c y puse un valor fijo para probar si tenia falla ahi, luego leyendo vi el tema de los delays y entre a preguntar al foro.
Por otra parte si la ignicion requiere un angulo de adelanto para sus diferentes rangos de funcionamiento, pero no pude variar el angulo, y como no podia realizar bien el disparo decidi enfocarme en disparara bien la inyeccion y luego ver la variacion de angulo de disparo el cual es otro de mis grandes problemas por que sin eso no enciende el vehiculo o falla demasiado.. Gracias, si pudiera darme una guia para ver como modificare el angulo de disparo de ignicion.
 
Última edición:
Ahí está la cosa; si programas 'hábilmente', con un un arduino te sobrará para todo . si lo hinchas a delays necesitarás tres arduinos por cilindro.
En principio usando los timers tienes "todo el tiempo del mundo" para ver el resto de cosas. Porque contar hasta 50, y encender y apagar un pin puede significar un 1% de gasto de CPU. Si usas retardos y bucles para comprobar lo que se comprueba solo... pues ya no tienes tiempo para nada.
Merece la pena emplear un poco de tiempo en aprender a usarlos.

En el que yo hice se podía hacer "puesta a punto" con el motor en marcha cambiando los tiempos de inyección y los de encendido, mostraba las rpm en un display y unas cuantas cosas mas y sobraba bastante cpu. Los valores de la puesta a punto se guardaban en la eeprom.
Esto parece tonto, pero es que el "interface de usuario" para controlar el teclado y el display suele ser el 80% de la aplicación o mas.
 
Última edición:
Gracias Joaquin, probare con esto, Tengo problemas con los disparos , y con el tiempo de duracion del mismo ayer probe y no me disparaba el tiempo que yo programaba, gracias por la ayuda, y pienso yo que el temp ==1 esta antes para verificar como primera condicion que el temporizador esta activado. por orden de prioridad, no se si estoy en lo correcto.
Otra consulta si añado comunicacion i2c, no me crearia mas retardo?
El serial utilizaba para comprobar el contador ya que el sensor me envia 4 picos de 5 voltios separados 3ms cada uno cada 180 grados de giro de el arbol de levas del motor, como tenia problemas al momento de disparar coloque el serial para verificar si estaba realizando la cuenta o se saltaba alguna interrupcion, Gracias por la ayuda



Los delays me nublaron la visión, jajaja

Mira la librería flexitimer que permite usar con facilidad los timers. Te simplificará bastante el código.

La decisión de empezar a inyectar yo la pondría en la interrupción; ahora mismo empiezas varias veces a inyectar y el tiempo no será exacto.

Para desconectar, mejor con timers porque con los milis del sistema tienes un error de +-1ms osea que lo mismo inyecta 6 que 7 ms según pilles los tics del sistema. Eso hará que el motor no vaya "redondo"

Parece que solo estás controlando la inyección; en la inyección indirecta es poco crítico cuando se inyecta la gasolina; ya lo absorberá el motor cuando entre en admisión. Lo que si que es muy crítico es el encendido.

Te falta algo mas; necesitas saber que hace el acelerador o la mariposa porque cuando se da un acelerón de golpe las uces de verdad enriquecen la mezcla durante un par de vueltas del motor.; de lo contrario entra demasiado aire de golpe con muy poco combustible y puede no encender por ser demasiado pobre.

Me parece que no controlas el encendido pero te comento que, descubrí que el motor arranca en frío muchísimo mejor si atrasas el encendido bastante; unos 30 o 45º, en seguida lo tienes que volver a ajustar porque si no lo haces irá mal y echará fuego por el escape. Bueno, eso era con etanol, no con gasolina, y parece que no hacía bien la mezcla y al esperar un poco el hecho es que arrancaba al primer pistonazo al hacer una cierta depresión y vaporizar bien el etanol en frío. Eso lo controlaba con las rpm, en cuanto subía de vueltas ponía el encendido en el punto muerto superior.

Yo haría esto en pseudocódigo
Código:
void cmp() {                                  // interrupción en pin 2
    cont_cmp++;                               // incrementamos el contador
si cuenta == a, b, c o d entonces
activa inyector
empieza timer
}

rutina del timer:
{
corta inyector
}

Ahora ya tienes todo el tiempo para todo lo demás; contar las rpm leer la mariposa etc

Gracias por la ayuda, si yo se que en inyeccion se que el tiempo de inyeccion debe variar segun a los valores de cada sensor del vehiculo, estoy trabajando con 2 arduinos uno me realiza el calculo de el tiempo de inyeccion y lo envia por i2c y el otro recibe y usa ese tiempo para la inyeccion, el problema es que no podia sincronizar bien el disparo por eso quite el valor que me enviaban por i2c y puse un valor fijo para probar si tenia falla ahi, luego leyendo vi el tema de los delays y entre a preguntar al foro.
Por otra parte si la ignicion requiere un angulo de adelanto para sus diferentes rangos de funcionamiento, pero no pude variar el angulo, y como no podia realizar bien el disparo decidi enfocarme en disparara bien la inyeccion y luego ver la variacion de angulo de disparo el cual es otro de mis grandes problemas por que sin eso no enciende el vehiculo o falla demasiado.. Gracias, si pudiera darme una guia para ver como modificare el angulo de disparo de ignicion.



En realidad... los estás inicializando a 1... Has puesto '==' en lugar de '='.

Además, no estás usando cont_ckp en ninguna otra parte del programa.

En el resto del programa... estás usando la función , que devuelve el número de milisegundos que el microcontrolador lleva encendido. Eso quiere decir que se trata de un valor que siempre está creciendo, por lo que la última condición (tiempoAnterior > tiempoig) siempre se cumplirá, pasados los primeros 6 ms.

Si lo que quieres es saber el tiempo que ha pasado el pin 12 en activo (temp == 1) entonces necesitas una variable más que marque el tiempo de inicio de ese periodo. tiempoAnterior hace justo esa labor. El problema es que la condición no es correcta. Debería ser algo así:

(millis() - tiempoAnterior > tiempoig)

De esa manera estás calculando el tiempo que ha pasado desde que inicializaste tiempoAnterior. Otro ejemplo:

Otro detalle: el envío de información por puerto serie es muy lento. Seguro que mucho más que los 6 ms de periodo de disparo que quieres en tu programa, así que esas instrucciones afectan al funcionamiento.

Recuerda también que las interrupciones 0 y 1 deben ir a los pines 2 y 3. Lo recomendable es usar la función de soporte

Sería algo así (no probado):
PHP:
#include <FreqCount.h>

int inyector = 12;                            // declaramos inyector al pin número 12
int tiempoig = 6;                             // tiempo de ignición en milisegundos

byte temp = 0;                                // detectar si está habilitado el temporizador
unsigned long tiempoAnterior = 0;             // guardar el valor de millis
volatile unsigned long cont_ckp, cont_cmp;    // contadores para sincronizar los sensores


void ckp() {                                  // interrupción en pin 3
    cont_cmp = 0;                             // reiniciamos el contador
}

void cmp() {                                  // interrupción en pin 2
    cont_cmp++;                               // incrementamos el contador
}

void setup() {
    attachInterrupt(digitalPinToInterrupt(3), ckp, RISING);      // interrupción en cambio a nivel alto
    attachInterrupt(digitalPinToInterrupt(2), cmp, FALLING);     // interrupción en cambio a nivel bajo

    pinMode(inyector, OUTPUT);                // declaramos inyector como salida

    //Serial.begin(9600);

    cont_cmp = 0;                             // iniciamos el contador en 0
    //cont_ckp = 0;                             // iniciamos el contador en 0
}

void activa_inyector() {
        tiempoAnterior = millis();            // inicializamos tiempoAnterior
        digitalWrite(inyector, HIGH);         // establecemos el pin12 en estado alto
        temp = 1;                             // el temporizador está activo
}

void desactiva_inyector() {
        tiempoAnterior = 0;                  // igualamos el contador a 0 para el próximo disparo
        digitalWrite(inyector,LOW);          // apagamos el pin12
        temp = 0;                            // y desactivo el temporizador
}

void loop() {
    if (cont_cmp == 4
    ||  cont_cmp == 8
    ||  cont_cmp == 12
    ||  cont_cmp == 16
    ) {                                      // si el contador es igual a 4, 8, 12 o 16
        activa_inyector();
    }

    // si ha transcurrido el periodo programado
    if (temp == 1  &&  (millis() - tiempoAnterior > tiempoig)) {
        desactiva_inyector();
    }

    //Serial.println(cont_cmp);
}
Como ejercicio para casa: ¿por qué he colocado temp == 1 en el lado izquierdo de la última condición?
 
Pues el uso del I2C u otras librerías te generará problemas dependiendo de como están programadas, cosa que desconocemos...
Por ejemplo la de los motores paso a paso es una catástrofe si no la han actualizado; mientras movieses un motor el sistema moría.
La uart tiene un buffer de 32 bytes de salida y 32 de entrada, así que mientras no lo satures va rápido.
El I2c, la verdad es que no he leído con detenimiento la documentación.
Claro, siempre hay que verificar que no hagan uso de recursos que tu uses por otro lado; las mismas interrupciones o timers o lo que sea.
 
Propongo que Scooter responda a todos los hilos en los que hay delay() con una respuesta acorde a su gusto en FORMA DE CÓDIGO que resuelva la cuestión del tema, y no en FORMA DE REPRIMENDA.

Decir que odias los delay() está bien, y yo lo comparto, pero para un novato, no le sirve de nada si no ve un ejemplo de lo que le estás contando.

Al menos... ponle un enlace a un ejemplo de lo que le estás proponiendo.

:aplauso: hace mas de un año que comento lo mismo... por lo menos somos dos ahora :apreton:

Respecto al tema inicial, entendi perfectamente lo que estas haciendo con tu rampa de inyectores y para no seguir desvirtuando como siempre pasa en los temas que se implementa la palabra "delay,pausa,etc" :rolleyes: te recomiendo hacer lo siguiente...
Una de las maneras, es 1ero configura e implemeenta el TMR0 como contador de la señal CMP; Es sabido que a tantos pulsos, el cigueñal esta en determinada posicion y por ende, las valvulas de cada cilindro estan en determiinada situacion... en cortitas palabras, sabemos en que ciclo esta cada piston.... Ahora... las pausas que estas usando para el tiempo de inyeccion, sacalas... Hace que se muevan con una variable, o sea,que el tiempo de inyeccion lo puedas poner vos a gusto tuyo. Este tiempo de energizacion, ronda los ms, tene en cuenta que el motor no se para para que puedas inyectar combustible en el cilindro, por lo tanto, tenes que tener en centa que el conteo tiene que estar en 2do plano y en lo posible, la accion de energizar el iinyector, tambien.... Es un poco complejo lo que estas queriendo hacer, pero no imposible.


PD: te recomiendo que le des un visto a este tema https://www.forosdeelectronica.com/f28/senales-banco-probador-ecu-72467/index4.html
PD2: no se necesita ningun diagrama... el que entiende aporta, el que no, aprende mirando :cool:

PD3: no lei todo el hilo por qe siempre se desvirtua... si me perdi algn comentario potable, disculpen
 
Se me olvidaba. Hay un dato más de por qué usar timers y no contar o restar la variable de sistema milis: ahora no me acuerdo pero millis es un long int o algo así y desborda cada cierto tiempo. Si una inyección pilla a mitad de desbordamiento puede hacer cualquier cosa absurda ya que t2 será inferior a t1.

Respecto a la propuesta del manual antidelays hace ya mucho tiempo publiqué cómo usar los timers sin la librería flexitimer. Es cuestión de usar el buscador del foro. Fue antes de que existiera esa librería. Una vez conocida la librería, basta con ver los ejemplos del código.
Sobre cómo se hace en otras plataformas que no uso, no puedo opinar. Podría bucear en mis proyectos antiguos y buscar cómo se hace en ensamblador del 8052 si es que a alguien le interesa.
Mis fuentes de los timers fueron un libro de M.Angulo del 6502 con la Pía 6520, 6522 y 6532 eso fue allá por el año 84 o así. Ese libro ya no lo tengo.

 
Se me olvidaba. Hay un dato más de por qué usar timers y no contar o restar la variable de sistema milis: ahora no me acuerdo pero millis es un long int o algo así y desborda cada cierto tiempo. Si una inyección pilla a mitad de desbordamiento puede hacer cualquier cosa absurda ya que t2 será inferior a t1.

La variable milis es un unsigned long y tarda aproximadamente 49 dias hasta desbordar. Aun asi es preferible controlar el tiempo de inyeccion con el/los timer del arduino.

Saludos.
 
En esos tiepos al no haber más que asm, no quedaba otra cosa, no había ningún lenguaje de alto nivel para micros y había que meter toto en mnemónicos en hexadecimal
mos_kim1.jpg

Esta una placa de entrenamiento de la época con el 6502
nec_tk80_1.jpg
 
como que no habia lengaje de alto nivel... y el BASCOM? no era compatible con los 6502, 8051,8085,Z80... puffff... de que año me estas hablando? ocheintimoneda largo o principios de los 80?
 
Atrás
Arriba