Skip to content

Instantly share code, notes, and snippets.

@matiasmicheletto
Last active August 27, 2020 23:00
Show Gist options
  • Save matiasmicheletto/35ccac7df155f61443ba3730ba8a8d59 to your computer and use it in GitHub Desktop.
Save matiasmicheletto/35ccac7df155f61443ba3730ba8a8d59 to your computer and use it in GitHub Desktop.
ATMega328 Arduino based dual channel variable frecuency square wave generator - Generador de onda cuadrada de frecuencia variable doble canal para Arduino
/*
* Doble generador de onda cuadrada de frecuencia variable
*/
// Pines
#define T1 2 // Salida 1
#define T2 3 // Salida 2
// Frecuencias por defecto (Hz)
#define DEF_1 3 // Salida 1
#define DEF_2 2 // Salida 2
// Frecuencia de oscilador interno
#define BASE 100.16
unsigned int tick1, tick2; // Contadores de pulsos del oscilador
unsigned int count1, count2; // Limite de cuenta
bool status1, status2; // Estado de salidas
void timerSetup(){
// Inicializa el oscilador interno
noInterrupts();
TCCR2A = 0; // Normal op.
TCCR2B = 0; // Normal op.
TCNT2 = 0; // Inicializar en 0
OCR2A = (byte) (16e6/1024.0/BASE/2.0); // Registro de comparación (valor = 16MHz/Prescaler/Freq)
TCCR2A |= (1 << WGM21); // Modo CTC
TCCR2B |= (1 << CS20); // 1024 prescaler
TCCR2B |= (1 << CS21); // 1024 prescaler
TCCR2B |= (1 << CS22); // 1024 prescaler
TIMSK2 |= (1 << OCIE2A); // Habilitar oscilador
interrupts();
}
bool togglePin(int n, bool status){
// Alternar estado de salida
digitalWrite(n, status ? HIGH:LOW);
return !status;
}
void updateFreq(float fr, int *cnt, int *tck){
// Actualizar el valor de frecuencia de una salida
if(fr > 0.0 && fr <= BASE){
*cnt = (int) (BASE/fr);
*tck = 0;
printStatus();
}else{
printError(fr);
}
}
void printStatus(){
// Imprime valores de frecuencia actuales
Serial.print("Valores actuales:\n");
Serial.print("Salida 1: ");
Serial.print(BASE/(float)count1);
Serial.print(" Hz, Salida 2: ");
Serial.print(BASE/(float)count2);
Serial.print(" Hz.\n\n");
}
void printHelp(){
// Muestra las instruncciones de uso
Serial.print("##### Generador de frecuencia ARDUINO #####\n");
Serial.print("Instrucciones de uso:\n");
Serial.print("\ta\tMuestra los valores de frecuencia actuales de las salidas 1 y 2.\n");
Serial.print("\th\tMuestra esta ayuda.\n");
Serial.print("\ts\tConfigurar frecuencia para la salida 1. Los valores válidos pueden ser entre 0 y 100Hz. Ejemplo \"s10\" --> Salida 1 a 10Hz.\n");
Serial.print("\tt\tConfigurar frecuencia para la salida 2. Los valores válidos pueden ser entre 0 y 100Hz. Ejemplo \"t0.5\" --> Salida 2 a 0.5Hz.\n\n");
}
void printError(float fr){
// Si se ingresa valor incorrecto
Serial.print("Error! El valor de frecuencia ingresado \"");
Serial.print(fr);
Serial.print("\" no es válido.\n\n");
Serial.print("Presione \"h\" para ver la ayuda.\n\n");
}
ISR(TIMER2_COMPA_vect){
// Rutina de interrupcion del oscilador
tick1++; tick2++;
if(tick1 == count1){
tick1 = 0;
status1 = togglePin(T1, status1);
}
if(tick2 == count2){
tick2 = 0;
status2 = togglePin(T2, status2);
}
}
void serialEvent(){
// Eventos de puerto serie
String arg;
float fr;
switch((char) Serial.read()){
case 'a': // Imprimir estado
printStatus();
break;
case 'h': // Imprimir ayuda
printHelp();
break;
case 's': // Configurar frecuencia salida 1
arg = Serial.readStringUntil('\n');
fr = arg.toFloat();
updateFreq(fr, &count1, &tick1);
break;
case 't': // Configurar frecuencia salida 2
arg = Serial.readStringUntil('\n');
fr = arg.toFloat();
updateFreq(fr, &count2, &tick2);
break;
default:
break;
}
}
void setup(){
Serial.begin(9600);
pinMode(T1, OUTPUT);
pinMode(T2, OUTPUT);
digitalWrite(T1, LOW);
digitalWrite(T2, LOW);
status1 = status2 = false;
tick1 = tick2 = 0;
count1 = (int) BASE/DEF_1;
count2 = (int) BASE/DEF_2;
timerSetup();
printHelp();
printStatus();
}
void loop(){}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment