/* Ejercicio entregable 2 - frecuencimetro */
//Configure el prescaler de los timers que use según sea su puesto de laboratorio, valor prescaler = 200 + 10*puesto de laboratorio.
//Con 2 botones se debe modificar (aumentar o disminuir) el tiempo de medida de la frecuencia (entre 1 y 9 segundos).
//Incluya un tercer botón para habilitar la señal de salida. De esta manera, por defecto, no se está generando la señal.
//Complete el diseño para que desde el puerto serie, se pueda modificar el valor de la frecuencia auto-generada.
//Nosotros estamos en el puesto 6 a las 10 de la mañana, por lo que nuestro valor de prescaler será 260
hw_timer_t * timer = NULL; //puntero a la estructura
volatile int cuenta = 0; // Cuenta las veces que han pasado los segundos que hemos definido
hw_timer_t * timer1 = NULL; //puntero a la estructura
volatile int mitad = 0; // Cuenta las veces que han pasado la mitad de los segundos que hemos definido
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 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.
const float frec_senyal = 5.8; // poner valores entre 1 y 25 Hz para el simulador, en la placa real se pueden elevar los tiempos
const float periodo_senyal_ms = 1000 * (1/frec_senyal); // periodo en ms
// incluimos las variables globales que vamos a necesitar durante el programa
volatile float inicio = 0; // Indica el inicio de la señal
volatile float nflancos = 0; // Cuenta el número de flancos
float nuevo_tiempo = 1; // 1 segundo inicialmente
volatile float valor_frec = nflancos / nuevo_tiempo; //valor de la frecuencia
volatile int subirfreq = 0; // Cuenta las veces que pulsamos el botón de subir la frecuencia
volatile int bajarfreq = 0; // Cuenta las veces que pulsamos el botón de bajar la frecuencia
// completamos el guion con las ISR que faltan
void IRAM_ATTR ISR_senyal_inicio(){ // Inicio de la señal
inicio++;
}
void IRAM_ATTR ISR_senyal_nflancos(){ // Contamos número de flancos
nflancos++;
}
void IRAM_ATTR ISR_sube(){ // Aumenta un segundo
subirfreq=1;
}
void IRAM_ATTR ISR_baja(){ // Disminuye un segundo
bajarfreq=1;
}
void IRAM_ATTR finTimer() { // Acaba el temporizador
cuenta=1;
}
void IRAM_ATTR finTimer1() { // Acaba el temporizador
mitad=2;
}
void setup(){
//Definiremos los timers y las interrupciones necesarias para ejecutar el loop
pinMode(senyal_output, OUTPUT); //Configuramos la señal como salida
Serial.begin(115200);
Serial.printf("\n Ejercicio entregable 2 - frecuencimetro" );
Serial.printf("\n Introduzca un valor para variar la frecuencia" );
//definimos los timers
//prescaler = 260 (200+10*6) y 80MHz/260 = 3,0769e5
volatile float resultado = 80e6/260; // resultado inicial
timer = timerBegin(0, 260, true);
timerAttachInterrupt(timer, &finTimer, true);
timerAlarmWrite(timer,resultado, true); //Queremos que se active cada segundo
timerAlarmEnable(timer);
timer1 = timerBegin(1, 260, true);
timerAttachInterrupt(timer1, &finTimer1, true);
timerAlarmWrite(timer1, resultado*periodo_senyal_ms/2000, true); //Queremos que se active cuando haya pasado medio periodo
timerAlarmEnable(timer1);
//definimos las interrupciones
attachInterrupt(digitalPinToInterrupt(18), ISR_senyal_nflancos, FALLING); // cada vez que exista un flanco de bajada, se contará un flanco
attachInterrupt(digitalPinToInterrupt(32), ISR_sube, FALLING); // cada vez que detecte un flanco de bajada, la frecuencia aumentará
attachInterrupt(digitalPinToInterrupt(33), ISR_baja, FALLING); // cada vez que detecte un flanco de bajada, la frecuencia disminuirá
attachInterrupt(digitalPinToInterrupt(35), ISR_senyal_inicio, FALLING); // habilitará y deshabilitará la frecuencia cada vez que detecte un flanco de bajada
}
void cambiarFrecuencia() {
Serial.println("Introduce la nueva frecuencia (en Hz): ");
while (!Serial.available()) {
// Espera a que haya datos disponibles en el puerto serie
}
// Lee la nueva frecuencia desde el puerto serie
float nuevaFrecuencia = Serial.parseFloat();
// Verifica si la entrada es válida
if (nuevaFrecuencia > 0) {
// Calcula el nuevo período
float nuevoPeriodo = 1 / nuevaFrecuencia;
// Deshabilita la alarma del temporizador
timerAlarmDisable(timer);
// Configura el nuevo período del temporizador
timerAlarmWrite(timer, nuevoPeriodo, true);
// Reinicia el temporizador
timerWrite(timer, 0);
// Habilita la alarma del temporizador
timerAlarmEnable(timer);
Serial.printf("Frecuencia cambiada a %.2f Hz\n", nuevaFrecuencia);
} else {
Serial.println("Entrada no válida. La frecuencia debe ser mayor que 0.");
}
}
void loop()
{
// función para cambiar la frecuencia de entrada usando el puerto serie
// función para crear la señal pulsando el interruptor
if (inicio!=0 && mitad==2) // ha pasado el tiempo completo: mitad+mitad=1
{
mitad = 0;
digitalWrite(senyal_output, !digitalRead(senyal_output) ); //Paso para cambiar la señal
}
// función para aumentar el tiempo de muestreo 1 segundo
volatile float resultado = 80e6/260;
volatile float refresh = resultado; // valor refrescado, en un principio es el mismo
if(subirfreq == 1 && refresh < resultado)
{
timerAlarmDisable(timer);
refresh = resultado + 1;
nuevo_tiempo = refresh/resultado;
timerAlarmWrite(timer, nuevo_tiempo, true);
timerWrite(timer, 0);
timerAlarmEnable(timer);
subirfreq = 0;
}
// función para disminuir el tiempo de muestreo 1 segundo
if(bajarfreq == 1 && refresh > resultado)
{
refresh = resultado - 1;
nuevo_tiempo = refresh/resultado;
timerAlarmWrite(timer, nuevo_tiempo, true);
timerWrite(timer, 0);
timerAlarmEnable(timer);
bajarfreq = 0;
}
if(cuenta==1){ //se ha producido la interrupción
cuenta=0;
float valor_frec=nflancos/nuevo_tiempo;
Serial.printf("Frec:%4.2f hz - nflancos: %.0f en %.0f seg \n ", valor_frec, nflancos, nuevo_tiempo );
nflancos=0;
}
//cambiarFrecuencia();
}