#define led_rojo 23
#define led_amarillo 22
#define led_verde 21
#define led_azul 19
#define led_naranja 18
#define pulsador_frecuencia 32
#define pulsador_ciclotrabajo 33
#define osciloscopio 26
volatile int cuenta = 0;
int LED[5] = {23,22,21,19,18}; //LEDs
int l=0; // índice para indicar el LED encendido
float frecuencia[5] = {3, 22, 42, 202, 402}; // valores de frecuencia en Hz
int i = 2; // índice para recorrer las frecuencias (tras el reset empieza en este valor)
volatile float PWM=42; // valor ciclo de trabajo (tras el reset empieza en este valor)
volatile float periodo=0;
float valor_cuenta=10000/3; //Defino variable tipo "float"-->Quiero que coja decimales
float valor_cuenta2=10000/300; //Si pusiera variable tipo "int"-->No me pondría decimales en el resultado de la operación
volatile int cuenta2=0;
int resolucion=100;
volatile float tiempo_encendido=0;
volatile float tiempo_apagado=0;
int tic;
int tac=0;
int imprimir=0;
int j=2;
hw_timer_t *timer = NULL;
hw_timer_t *timer2 = NULL;
void IRAM_ATTR fintimer() //Se debe de incrementar después de que cuenta2 llegue a 100
{
cuenta++;
if (cuenta > 10) //La secuencia va de 1 a 10 periodos de la señal
cuenta = 1;
}
void IRAM_ATTR actualizarFrecuencia()
{
detachInterrupt(digitalPinToInterrupt(pulsador_frecuencia)); //Elimino rebotes al presionar
j++;//Guardo la pulsación en otra variable y espero que acabe la secuencia para incrementar la frecuencia
if(j>4)
j=0;
}
//Calculo el valor_cuenta2 en la interrupción asociada al pulsador de frecuencia ya que solo cambia valor_cuenta2 con la acción de este pulsador
void IRAM_ATTR rebotes()
{
detachInterrupt(digitalPinToInterrupt(pulsador_frecuencia));//Elimino rebotes al soltar
}
void IRAM_ATTR fintimer2() //Cada 100 de cuenta2, se tiene que incrementar en 1 cuenta
{
cuenta2++;
if(cuenta2==100)
{
i=j;
valor_cuenta = 10000/frecuencia[i]; //Calcula el número de cuentas que tiene que contar el timer para que se active la alarma con cada valor de frecuencia
timerAlarm(timer, valor_cuenta, true, 0); // Actualiza la alarma del temporizador
valor_cuenta2 = 10000/(resolucion*frecuencia[i]); //Calcula el número de cuentas que tiene que contar el timer2 para que se active la alarma con cada una de las 100 partes del ciclo asociado al valor de frecuencia
timerAlarm(timer2, valor_cuenta2, true, 0); // Actualiza la alarma del ciclo de trabajo
}
if(cuenta2<PWM)
{
digitalWrite(LED[l], HIGH);//Pone en HIGH solo cierto porcentaje del ciclo del LED (correspondiente al PWM)
digitalWrite(osciloscopio, HIGH); //Muestra la señal a medir en el osciloscopio, mostrando la información de cada uno de los leds cuando está encendido
}
else{
digitalWrite(LED[l], LOW);
digitalWrite(osciloscopio, LOW);
}
if(cuenta2>=resolucion) //Va de 0 a 100 partes de la señal
cuenta2=0;
}
void IRAM_ATTR cambiarciclotrabajo()
{
detachInterrupt(digitalPinToInterrupt(pulsador_ciclotrabajo)); //Elimino rebotes al presionar
PWM=PWM+9;
if (PWM > 99)
PWM = 9;
}
void IRAM_ATTR rebotes2()
{
detachInterrupt(digitalPinToInterrupt(pulsador_ciclotrabajo)); //Elimino rebotes al soltar
}
void setup()
{
Serial.begin(115200);
pinMode(led_rojo, OUTPUT);
pinMode(led_amarillo, OUTPUT);
pinMode(led_verde, OUTPUT);
pinMode(led_azul, OUTPUT);
pinMode(led_naranja, OUTPUT);
pinMode(pulsador_frecuencia, INPUT);
pinMode(pulsador_ciclotrabajo, INPUT);
pinMode(osciloscopio,OUTPUT);
// Configuración del temporizador
timer = timerBegin(10e3); // Timer 10000 ya que tiene que ser mayor que 1250 --> Vemos que en frecuencias altas, el timer tiene un error
//El error viene de que como el Timer tenía una frecuencia relativamente baja, no podía ejecutar la alarma, ya que no cabe el valor de cuenta de la alarma en el Timer
//Esto se soluciona poniendo una frecuencia del timer Mucho mayor, que permite que la alarma en frecuencias muy grandes sí quepa en los valores que cuenta el Timer
timerAttachInterrupt(timer, &fintimer);
timerAlarm(timer, valor_cuenta, true, 0);
//Hay que meter la alarma en el setup, porque si no al inicio no se ejecuta
//Como está definida en la interrupción del pulsador, solo se ejecuta si se activa el pulsador
//Configuración del temporizador 2
timer2 = timerBegin(10e3);
timerAttachInterrupt(timer2, &fintimer2);
timerAlarm(timer2, valor_cuenta2, true, 0);
}
void loop()
{
if(digitalRead(pulsador_frecuencia)==1)
attachInterrupt(digitalPinToInterrupt(pulsador_frecuencia),actualizarFrecuencia,FALLING);
//Pongo el attachInterrupt dentro del Loop ya que desactivamos la interrupcion en la ISR para eliminar rebotes
//Si no, se podría definir en setup
if(digitalRead(pulsador_frecuencia)==0)
attachInterrupt(digitalPinToInterrupt(pulsador_frecuencia),rebotes,RISING);
//Tengo que quitar los rebotes tanto cuando pulso como cuando suelto
//Asocio cada interrupción al estado de pulsador
if(digitalRead(pulsador_ciclotrabajo)==1)
attachInterrupt(digitalPinToInterrupt(pulsador_ciclotrabajo),cambiarciclotrabajo,FALLING);
if(digitalRead(pulsador_ciclotrabajo)==0)
attachInterrupt(digitalPinToInterrupt(pulsador_ciclotrabajo),rebotes2,RISING);
switch (cuenta)
//Como en el default pongo todos los LEDs en LOW, esto se mantiene y por lo tanto solo me hace falta encender el que toque según el periodo.
//En los casos pares de cuenta (default) se van a volver a poner todos en low y esto se mantiene salvo que se diga lo contrario
{
//En vez de High, llamo a una función que me pone el ciclo de trabajo que tiene que ser en cada case
case 1:
l=0;
break;
case 3:
l=1;
break;
case 5:
l=2;
break;
case 7:
l=3;
break;
case 9:
l=4;
break;
default:
l=-1; //Después de usar la variable, no le asigno el valor de ningún LED para que no haga el ciclo de trabajo en ninguno
digitalWrite(led_rojo, LOW);
digitalWrite(led_amarillo, LOW);
digitalWrite(led_verde, LOW);
digitalWrite(led_azul, LOW);
digitalWrite(led_naranja, LOW);
}
//Cuentas: Para que me de el resultado con decimales, TODAS las variables que estén en la operación deben de ser tipo "float"
periodo = 1000/frecuencia[i];
tiempo_encendido = periodo * (PWM/100);
tiempo_apagado = periodo-(periodo*(PWM/100));
//Hago que se imprima la información cada 2 segundos con la función millis()
tic=millis();
if(tic>2000+tac)
{
tac=tic;
imprimir=1;
}
if(imprimir==1)
{
Serial.print("Frecuencia (Hz): ");
Serial.println(frecuencia[i]);
Serial.print("Ciclo de trabajo (%): ");
Serial.println(PWM);
Serial.print("Tiempo encendido (ms): ");
Serial.println(tiempo_encendido);
Serial.print("Tiempo apagado (ms): ");
Serial.println(tiempo_apagado);
Serial.print("Periodo (ms): ");
Serial.println(periodo);
imprimir=0;
}
delay(10);
}