Soy programador y no tengo experiencia con arduino ni con ningún microcontrolador. Especialmente la parte técnica.
He soldado una matriz de leds RGB de 6x8 y uso modulación codificada binaria http://www.batsocks.co.uk/readme/art_bcm_3.htm para mezclar los colores.
Los Leds son controlados por 4 74hc595 shiftregisters. Básicamente cambio los bits para controlar lo realmente rápido durante una interrupción del temporizador.
Ahora quiero influir en el color de los leds midiendo las frecuencias de sonido con un Placa de conexión para micrófono electret . Para lograr una detección rápida de la frecuencia, utilizo una técnica descrita aquí http://www.instructables.com/id/Arduino-Frequency-Detection/#step1 .
Se basa en las interrupciones del CAD.
Ambas implementaciones funcionan solas, pero cuando intento unir el código se rompe.
El temporizador y el ADC se inicializan así:
cli(); //stop all interrupts
/////////////////////
//initialize TIMER//
////////////////////
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 1; // compare match register
TCCR1B |= (1 << WGM12); // CTC mode
TCCR1B |= ((1<<CS21)|(1<<CS20)) ;
TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
//////////////////
//initialize ADC//
//////////////////
ADCSRA = 0;
ADCSRB = 0;
ADMUX |= (1 << REFS1); //set reference voltage
ADMUX |= (1 << ADLAR); //left align the ADC value- so we can read highest 8 bits from ADCH register only
//ADCSRA |= (1 << ADPS2) | (1 << ADPS0); //set ADC clock with 32 prescaler- 16mHz/32=500kHz
ADCSRA |= (1 << ADATE); //enabble auto trigger
ADCSRA |= (1 << ADIE); //enable interrupts when measurement complete
ADCSRA |= (1 << ADEN); //enable ADC
ADCSRA |= (1 << ADSC); //start ADC measurements
sei(); //start all interrupts
Así que mi pregunta es: ¿es posible utilizar esas interrupciones juntas? Y cómo tengo que configurarlos para que funcione. ¿O es un callejón sin salida?
EDITAR La interrupción del temporizador:
ISR(TIMER1_COMPA_vect) // timer compare interrupt service routine
{
zaehlbit <<=1;
//reset timercompare and zaehlbit
if( zaehlbit == 0 ) {
OCR1A= 1;
zaehlbit = 1;
}
//latch low
bitClear(PORTB, latchPinPORTB);
//red
for (int i=0; i<8; i++){
// clock low
bitClear(PORTB, clockPinPORTB);
//check led position and brightness
//and set Bit on Datapin if zaehlbit in Brightness
if (ledCounter&led && zaehlbit&red){
bitClear(PORTB, dataPinPORTB);
}
else {
bitSet(PORTB, dataPinPORTB);
}
// clock low (register bit)
bitSet(PORTB, clockPinPORTB);
ledCounter >>= 1;
if( ledCounter == 0 ) {
ledCounter = 128;
}
}
//shift timer compare and set timer back to generate delay (Bit Angle Modulation)
OCR1A <<= 1;
TCNT1 = 0;
}
Hago el mismo bucle for para las filas y los otros colores. Lo dejé fuera porque parecía confuso. El registro de comparación se desplaza a la izquierda durante la interrupción y el temporizador se retrasa para generar un retardo "creciente". Hay una interrupción por ciclo. Se ejecuta en un reloj/32 tickrate
La interrupción del ADC tiene este aspecto:
ISR(ADC_vect) {//when new ADC value ready
prevData = newData;//store previous value
newData = ADCH;//get value from A0
if (newData > prevData){//if positive slope
bitSet(PORTB, ledPORTB);//set pin 12 high
}
else if (newData < prevData){
bitClear(PORTB, ledPORTB); //set pin 12 low
}
}
La interrupción del ADC se activa cada vez que un valor de A0 está listo. En el bucle principal intento poner algunos leds pero no funciona.
1 votos
Por supuesto, debería ser posible. ¿Podría explicar un poco más? ¿Qué es exactamente lo que no funciona como se espera? También, podrías publicar el código completo (o al menos los manejadores de interrupción y tu bucle principal). También: ¿Con qué frecuencia esperas una interrupción del ADC y con qué frecuencia esperas que se produzca la interrupción del temporizador?
0 votos
He editado la pregunta espero que sea más clara ahora
1 votos
Consulta la hoja de datos de tu microcontrolador exacto (ATmega[algo]). Cada interrupción tiene su propio vector y viene con su propia prioridad, esto define qué interrupción será atendida cuando dos llegan al mismo momento. Mientras una interrupción es atendida, la otra interrupción será puesta en espera hasta que la primera ISR termine.
2 votos
¿Cuál es su frecuencia de reloj? ¿Estás activando la interrupción del temporizador cada ciclo de reloj (debido a OCR1A = 1)? ¿Tal vez el tiempo de ejecución del ISR del temporizador es más largo que el intervalo de interrupción? ¿Qué significa exactamente "cuando intento juntar el código se rompe"?