#define DEBUG(a) Serial.println(a); // Para modificar el valor de la frecuencia auto-generada desde el puerto serie
#define debounce_time 200 //TIEMPO A ESPERAR PARA EVITAR REBOTES PULSADOR
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 senyal=34;//PIN AL QUE CONECTAMOS PULSADOR PARA HABILITAR SEÑAL
const int sube = 32; //PIN AL QUE CONECTAMOS PULSADOR PARA SUBIR DURACIÓN TIMER
const int baja = 33; //PIN AL QUE CONECTAMOS PULSADOR PARA BAJAR DURACIÓN TIMER
hw_timer_t *timer = NULL;//DECLARAMOS PUNTERO TIMER
volatile unsigned long current_millis=0,last_interrupt=0;
volatile unsigned long current_millis1=0,last_interrupt1=0; /*declaramos 6 variables que usaremos para fines temporales. Son de carácter volátil ya que son utilizadas en los bloque de instrucciones de los timers*/
volatile unsigned long current_millis2=0,last_interrupt2=0;
volatile int senyal_habilitada=0;
float frecuencia=5.8; // frecuencia inicial con su periodo
float periodo_senyal_ms=1000 *(1/frecuencia);
volatile double duracion=307692.3077; // Valor de intervalo inicial para la medida de la frecuencia
volatile double segundo=307692.3077; //
volatile double frecuencia_medida=0;
volatile double flancos=0; // variables para obtener el valor de la frecuencia medida y nº de flancos
volatile int a=0;
volatile int n=0;
void IRAM_ATTR finTimer() { /* Bloque de la ISR del timer: para obtener la frecuencia*/
frecuencia_medida=(flancos)/(duracion/segundo);
a=flancos;
flancos=0;
n=1;
}
void IRAM_ATTR ISR_cuenta(){
flancos++; /* aumentamos el número de flancos cada vez que se habilite la señal*/
}
void IRAM_ATTR ISR_sube(){ /*Bloque de la ISR para subir el tiempo de medida*/
current_millis2=millis(); // empezamos a contar el tiempo antes del bloque principal
if (current_millis2 - last_interrupt2 > debounce_time){
flancos=0; // si el tiempo desde la última interrupción es mayor al tiempo para evitar rebotes desactivamos la alarma del timer.
timerAlarmDisable(timer);
if(duracion<9*segundo){ // Si pulsamos el boton de subida, aumentaremos el tiempo de subida teniendo como límite 9s
duracion=duracion+segundo;
}
timerAlarmWrite(timer,duracion,true); // Luego cambiamos la alarma con su nuevo intervalo de activación
timerWrite(timer,0);
if(senyal_habilitada==1){ // Habilitamos la nueva alarma si la señal esta habilitada, es decir, al pulsar el boton que control el paso de la señal.
timerAlarmEnable(timer);}
last_interrupt2 = current_millis2;
}
}
void IRAM_ATTR ISR_baja(){ /*Bloque de la ISR para subir el tiempo de medida*/
current_millis1=millis(); // empezamos a contar el tiempo antes del bloque principal
if (current_millis1 - last_interrupt1 > debounce_time){
flancos=0;
timerAlarmDisable(timer); // si el tiempo desde la última interrupción es mayor al tiempo para evitar rebotes desactivamos la alarma del timer
if(duracion>segundo){ // Si pulsamos el boton de subajada, disminuiremos el tiempo de subida teniendo como límite 1s
duracion=duracion-segundo;
}
timerAlarmWrite(timer,duracion,true); // Luego cambiamos la alarma con su nuevo intervalo de activación
timerWrite(timer,0);
if(senyal_habilitada==1){
timerAlarmEnable(timer);} // Habilitamos la nueva alarma si la señal esta habilitada, es decir, al pulsar el boton que control el paso de la señal.
last_interrupt1 = current_millis1; //igualamos el tiempo contado con el de la última interrupción
}
}
void IRAM_ATTR ISR_senyal(){
current_millis=millis(); // empezamos a contar el tiempo antes del bloque principal
if (current_millis - last_interrupt > debounce_time) // si el tiempo desde la última interrupción es mayor al tiempo para evitar rebotes desactivamos/activamos el timer dependiendo del estado de la señal habilitada
{
if(senyal_habilitada==0){
senyal_habilitada=1;
flancos=0; // si la señal está habilitada, reiniciamos nº de flancos
timerWrite(timer,0); // activamos el timer después de reiniciarlo a 0
timerAlarmEnable(timer);
}
else{
senyal_habilitada=0;
flancos=0; // si la señal está deshabilitada, reiniciamos nº de flancos
timerWrite(timer,0); // desactivamos el timer después de reiniciarlo a 0
timerAlarmDisable(timer);
}
last_interrupt = current_millis; //igualamos el tiempo contado con el de la última interrupción
}
}
void setup(){
Serial.begin(9600);
Serial.print("INTRODUZCA EL VALOR DE LA FRECUENCIA EN Hz\n"); /*Mandamos mensaje para el usuario*/
pinMode(senyal_output, OUTPUT);
pinMode(senyal_entrada,INPUT); /*Declaración de pines como entradas excepto la salida de la señal*/
pinMode(sube,INPUT);
pinMode(baja,INPUT);
pinMode(senyal,INPUT);
attachInterrupt(digitalPinToInterrupt(senyal),ISR_senyal,FALLING);
attachInterrupt(digitalPinToInterrupt(sube),ISR_sube,FALLING); /*Declaramos la llamada de 4 interrupciones: 1 para aumentar el tiempo de medida de la frecuencia con un pulsador, otra para disminuirlo con otro pulsador, otra cuando se habilita la señal de entrada y cuando se hace la medida de la frecuencia*/
attachInterrupt(digitalPinToInterrupt(baja),ISR_baja,FALLING);
attachInterrupt(digitalPinToInterrupt(senyal_entrada),ISR_cuenta,FALLING);
timer=timerBegin(0, 260, true);
timerAttachInterrupt(timer, &finTimer, true); /*Inicializamos un timer con un valor de división del tiempo 260, para contar el flanco ascendente de la señal. Luego le asociamos una función ISR que se activa por flanco, por último, programar una alarma que se activará a un intervalo cálculado previamente. */
timerAlarmWrite(timer, duracion, true);
}
unsigned long tp1=0;
unsigned long current_time; // declaramos 2 variables más que usaremos para fines temporales
void loop()
{
if(Serial.available()>0){
flancos=0;
String str = Serial.readStringUntil('\n'); // activación del puerto serie para meter la frecuencia auto-generada
float frecuencia = str.toFloat();
Serial.printf("NUEVA FERECUENCIA %4.2f Hz\n",frecuencia); // mensaje de esa frecuencia elegida
periodo_senyal_ms=1000*(1/frecuencia);
timerWrite(timer,0);}
if(n==1){
Serial.printf("La frecuencia medida es %4.2f Hz en %4.0f segundos con flancos contados %d\n",frecuencia_medida,duracion/segundo,a); // mensaje de frecuencia medida con su intervalo de tiempo y el número de flancos ascendentes
n=0;
}
if(senyal_habilitada==1){
delay(1);
current_time=millis();
if( current_time-tp1 > periodo_senyal_ms/2){
digitalWrite(senyal_output, !digitalRead(senyal_output) );
tp1=millis(); // reset a tp1
}
}
}