#define valor fc_pre 220
#define debounce_time 200
hw_timer_t * timer0 = NULL; // estructura de datos del timer
hw_timer_t * timer1 = NULL; // estructura de datos del timer
const int senyal_output = 23; // pin generacion señal simulación -> en el lab, conectar generador de funciones
const int senyal_entrada = 18; // GPIO pin interrupcion para la entrada de señal
const int parar = 25;
const int sube = 32; // aumenta 1 seg el tiempo de medida, hasta 10 seg.
const int baja = 33; // disminuye 1 seg el tiempo de medida, hasta 1 seg.
float frec_senyal = 5.8; // poner valores entre 1 y 25 Hz para el simulador, en la placa real se pueden elevar los tiempos
float periodo_senyal_s = (1/frec_senyal); // periodo en segundos
float crono = 5; // determina cada cuántos segundos se realiza la medición
float valor_frec; // almacena el valor de la frecuencia
int medir = 0; // caundo la interrupción
volatile unsigned long current_millis = 0; // va tomando el tiempo transcurrido
volatile unsigned long last_interrupt_time_sube = 0;
volatile unsigned long last_interrupt_time_baja = 0;
volatile unsigned long last_interrupt_time_parar = 0;
volatile int nflancos = 0; // cuenta el número de flancos
int paro = 0;
int entrada = 0;
String str;
void IRAM_ATTR ISR_senyal()
{
digitalWrite(senyal_output, !digitalRead(senyal_output) ); // Alterna entre 0 y 1 la señal de simulación cuadrada
}
void IRAM_ATTR ISR_senyal_2()
{
nflancos++; // cuenta los flancos de bajada
}
void IRAM_ATTR ISR_medir()
{
medir = 1;
}
void IRAM_ATTR ISR_parar ()
{
current_millis = millis();
// Si la IRQ viene antes de “debounce_time” ms, se asume que es un "rebote"
if (current_millis - last_interrupt_time_parar > debounce_time)
{
if (paro == 0)
{
paro = 1;
timerAlarmDisable(timer0); //inhabilitamos el timer0
timerAlarmDisable(timer1); //inhabilitamos el timer1
nflancos = 0;
}
else
{
paro = 0;
timerAlarmWrite(timer0, (8e7/220)*(periodo_senyal_s/2), true); //volvemos a poner el tiempo
timerWrite(timer0,0); // ponemos e tiempo a 0
timerAlarmEnable(timer0); // volvemos a hablitar la alarma
timerAlarmWrite(timer1, (8e7/220)*crono, true); // modificamos al nuevo tiempo
timerWrite(timer1,0); // ponemos e tiempo a 0
timerAlarmEnable(timer1); // volvemos a hablitar la alarma
nflancos = 0;
medir = 0;
}
}
last_interrupt_time_parar = millis();
}
void IRAM_ATTR ISR_sube()
{
current_millis = millis();
// Si la IRQ viene antes de “debounce_time” ms, se asume que es un "rebote"
if (current_millis - last_interrupt_time_sube > debounce_time)
{
crono++;
if (crono > 10) // si supera los 10 segundos se queda en 10
{
crono = 10;
}
timerAlarmDisable(timer1); // se desactiva la alarma antes de modificar el tiempo
timerAlarmWrite(timer1, (8e7/220)*crono, true); // modificamos al nuevo tiempo
timerWrite(timer1,0); // ponemos e tiempo a 0
timerAlarmEnable(timer1); // volvemos a hablitar la alarma
nflancos = 0;
}
last_interrupt_time_sube=current_millis;
}
void IRAM_ATTR ISR_baja()
{
current_millis = millis();
// Si la IRQ viene antes de “debounce_time” ms, se asume que es un "rebote"
if (current_millis - last_interrupt_time_baja > debounce_time)
{
crono = crono - 1;
if (crono < 1) // si es inferior a 1 se queda a 1 segundo
{
crono = 1;
}
timerAlarmDisable(timer1); // se desactiva la alarma antes de modificar el tiempo
timerAlarmWrite(timer1, (8e7/220)*crono, true); // modificamos al nuevo tiempo
timerWrite(timer1,0); // ponemos e tiempo a 0
timerAlarmEnable(timer1); // volvemos a hablitar la alarma
nflancos = 0;
}
last_interrupt_time_baja=current_millis;
}
void setup()
{
Serial.begin(9600);
Serial.println("Introduzca la frecuencia en Hz si lo desea (por defecto está a 5.8 Hz)");
pinMode(senyal_output, OUTPUT); // seteamos el pin de entrada de la señal
pinMode(senyal_entrada, INPUT); // setamos el pin de salida de la señal
pinMode(sube, INPUT); // seteamos el pin de
pinMode(baja, INPUT);//
timer0 = timerBegin(0, 220, true); // ponemos el preescaler al valor requerido (220) y seteamos el timer0, encargado del tiempo de subida y bajada de la señal de simulación
timerAttachInterrupt(timer0, &ISR_senyal, true); // ponemos la interrupción para el timer 0
timer1 = timerBegin(1, 220, true); // seteamos el timer1 con el preescaler a 220, este timer está encargado del tiempo entre mediciones
timerAttachInterrupt(timer1, &ISR_medir, true); // ponemos la interrupción del timer 1
timerAlarmWrite(timer0, (8e7/220)*(periodo_senyal_s/2), true); // la alarma de la señal se activa cada la mitad del periodo en segundos
timerAlarmWrite(timer1, (8e7/220)*5, true); // la alarma de la medición se activa cada 5 segundos incialmente
attachInterrupt(senyal_entrada,ISR_senyal_2,FALLING); //interrupción para contar los flancos de bajada
timerAlarmEnable(timer0); // habilitamos el timer0
timerAlarmEnable(timer1); // habilitamos el timer1
attachInterrupt(sube,ISR_sube,FALLING); // interrupciones para el pulsador de subir el tiempo de medida
attachInterrupt(baja,ISR_baja,FALLING); // interrupción para el pulsador de bajar el tiempo de medida
attachInterrupt(parar,ISR_parar,FALLING);
}
void loop()
{
delay(10);
//leemos el puerto serie si hay algo
if ((Serial.available()>0))
{
delay(5);
str = Serial.readStringUntil('\n'); // eliminamos el valor del enter ya que en caso contrario toma el valor 0
frec_senyal = str.toFloat(); // pasamos de string a float
entrada = 1;
}
if (entrada == 1)
{
periodo_senyal_s = (1/frec_senyal); //tomamos el nuevo valor del periodo
Serial.printf("frecuencia introducida: %4.2f \n",frec_senyal); //imprimimos
timerAlarmDisable(timer0); //inhabilitamos el timer0 para cambiar su tiempo de alarma
timerAlarmWrite(timer0, (8e7/220)*(periodo_senyal_s/2), true); //volvemos a poner el tiempo
timerWrite(timer0,0); // ponemos e tiempo a 0
timerAlarmEnable(timer0); // volvemos a hablitar la alarma del timer0
timerAlarmDisable(timer1); // se desactiva la alarma antes de modificar el tiempo de alarma
timerAlarmWrite(timer1, (8e7/220)*crono, true); // modificamos al nuevo tiempo
timerWrite(timer1,0); // ponemos e tiempo a 0
timerAlarmEnable(timer1); // volvemos a hablitar la alarma
nflancos = 0;
entrada = 0;
}
if (medir == 1) // se ha activado la interrupción de medir (no podemos utilizar Serial.print dentro de una interrupción)
{
medir = 0; // ponemos medir a 0 para que solo entre 1 vez por cada interrupción en el if
valor_frec = (nflancos/crono); // medimos la frecuencia
Serial.printf("Frec: %4.2f - nflancos: %d \n", valor_frec, nflancos); // imprimimos por pantalla el valor de la frecuencia
nflancos= 0; // reseteamos el nçumero de flancos a 0 para la siguiente medición
}
}