Lo hago desde el IDE del arduino pero accediendo a algunas cosas del hard directamente.
Un par de notas previas:
De programar en C estoy pez; pese a haberlo intentado en las últimas décadas nunca lo he "interiorizado" osea que es probable que tenga errores muy muy básicos.
Programar en código máquina si que se, lo he hecho durante años en varias plataformas.
El problema:Mediante interrupciones para cargar lo mínimo la CPU hago lo siguiente. Un sensor hall manda un pulso que activa una salida y un tiempo después se apaga. Ambas señales van por interrupciones; una externa para inicio y una por el timer2 para el final. Parece funcionar correctamente, pero al haber añadido unas instrucciones para contar el tiempo de la amplitud del pulso salen tiempos muy grandes.
No he podido medir la amplitud real del pulso y puede que sea correcta y el "medidor" con lafunción millis() o con micros() da mas o menos lo mismo no mida bien porque las funciones del sistema sean muy lentas.
El caso es que el tiempo mínimo son 16mS y debería de ser menos.
El código:Código: Seleccionar todo
#include <avr/interrupt.h>
#include <avr/io.h>
int Inyector = 3; //
int LED = 13; //Pin del led
int PotOn=A0;
int recarga=100;
int RPM;
unsigned long tOn=0;
unsigned long tOnOld;
unsigned long apertura;
volatile int state = LOW;
//
ISR(TIMER2_OVF_vect) {
digitalWrite( Inyector, LOW);
//Parar el timer 2
TCCR2B &= ((0<<CS22) | (0<<CS21) | (0<<CS20));
//TIMSK2 |= (0<<TOIE2) ; //InHabilita interrupción por desbordamiento del Timer2
apertura=millis()-tOn;
state = !state;
Serial.print("R=");
Serial.print(recarga);
Serial.print(" Ap=");
Serial.print(apertura);
Serial.print("mS ");
Serial.print(RPM);
Serial.println("rpm");
};
void setup() {
//Parar el timer 2
TCCR2B &= ((0<<CS22) | (0<<CS21) | (0<<CS20));
// Use normal mode
TCCR2A |= (0<<WGM21) | (0<<WGM20);
// Usar reloj interno. No se usa el reloj externo en arduino
ASSR |= (0<<AS2);
TIMSK2 |= (1<<TOIE2) | (0<<OCIE2A); //Habilita interrupción por desbordamiento del Timer2
//Initialize serial and wait for port to open:
Serial.begin(9600);
// prints title with ending line break
Serial.println("ECU 004 (c) Felix Diaz");
// initialize the digital pin as an output.
pinMode(Inyector, OUTPUT);
pinMode (LED , OUTPUT);
attachInterrupt(0, inicio, FALLING); //Puede ser LOW, CHANGE, RISING Y FALLING
}
void loop() {
recarga=255-analogRead(PotOn)/4; //El potenciometro va al revés que el timer
digitalWrite(LED, state);
delay(100);
}
void inicio()
{
digitalWrite( Inyector, HIGH);
tOnOld=tOn;
tOn=millis();
sei();
//Recargar el timer:
TCNT2=recarga;
//Configuración del timer 2: Preescaler /1024,
TCCR2B |= ((1<<CS22) | (1<<CS21) | (1<<CS20));
//Resetear el preescaler
GTCCR |= (1<<PSRASY);
RPM=60000/(tOn-tOnOld);
}
Dado lo taruguín que soy programando en C, a ver si veis algún error gordo o algo. Es probable que tenga alguna orejada tonta.
Otra idea que he tenido es usar otro arduino para leer lo que hace este, pero si es que no hacen bien el cálculo del tiempo lo mismo va a dar.
Creo que el medidor va bien; he estado generando pulsos a mano de 1Hz y el medidor de rpm da 60 que es lo correcto, osea que parece que por algún motivo desconocido se tarda 16ms adicionales en ejecutar una interrupción, y 16ms en un animalito que va a 16MHz son una eternidad o dos.
Me huele a que no inicializo bien las interrupciones o algo semejante y que hace un ciclo completo de 256 en el timer que corresponden a los 16ms y después ya hace el ciclo programado con lo que sea. Por eso varía entre 16 y unos 32ms. Pero realmente no se donde está la cuestión. Debería de durar entre "cero" y 16ms. Cero no podrá ser pero vamos, casi cero y 16ms.