Ca c'est un bon prof soucieux de faire des projets interessant à ses élèves dis donc ! ^^
Héhé, il faut bien réussir à les intéresser un peu ^^
J'aurais bien voulu avoir des projets de ce style durant ma scolarité...
Bon, pour le moment, j'essaye d'échantillonner un signal à 44.1kHz, de le convertir sur 8 bits et de l'écrire sur un des ports de l'Arduino.
Comme ça, je serais capable de tester toute la chaine du montage en écoutant en sortie le signal d'entrée.
Mais c'est moins simple que ça en à l'air ! Avec Arduino, on ne peut pas dépasser les 15KHz en échantillonnage :/ Du coup, je dois configurer directement l'Atmel.
Pour le moment, j'ai réussi à échantillonner à 44.1kHz et j'ai configurer le convertisseur analogique numérique pour qu'il puisse échantillonner à 77kHz max.
#define FASTADC 1
// defines for setting and clearing register bits
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
int sample;
void setup() {
#if FASTADC
// set prescale to 16
sbi(ADCSRA,ADPS2) ; // 1
cbi(ADCSRA,ADPS1) ; // 0
cbi(ADCSRA,ADPS0) ; // 0
#endif
// Initialisation du port7 (arduino Mega : pin 42 à 49)
for(int i = 0; i < 8; i++) {
pinMode(42+i,OUTPUT);
}
//pinMode(13,OUTPUT);
DDRB = 0xFF;//all outputs
// Configuration du timer1.
// Interruption à 40kHz
noInterrupts();
TCCR1A = B00000000;// set entire TCCR0A register to 0
TCCR1B = B00000000;// same for TCCR0B
TCNT1 = 0;//initialize counter value to 0
//OCR1A = 49;// = (16*10^6) / (40000*8) - 1 (must be <256)
OCR1A = 362;// = (16*10^6) / (44100) - 1 (must be <256) (44077Hz)
TCCR1B |= (1 << WGM12); // CTC
//TCCR1B |= (1 << CS11); // prescale8
TCCR1B |= (1 << CS10); // prescale1
//TIMSK1 |= (1 << OCIE0A); // timer compare interrupt enable
TIMSK1 |= (1 << OCIE1A); // timer compare interrupt enable
interrupts();
}
// Interruption timer 1
ISR(TIMER1_COMPA_vect){ //40kHz interrupt routine
PORTB = PORTB ^ B10000000;
//sample = analogRead(0);
//PORTL = sample/4;
}
void loop(){
}
Le code est encore un peu en vrac, mais il est fonctionnel.
Sans code dans l'interruption du timer, je suis bien à 44.1kHz.
Si j'essaye d'échantillonner, je tombe à 41.5kHz
Et si en plus, j'essaye d'écrire sur le port L, je tombe cette fois à 25.5kHz :/ (ce qui veut dire qu'arduino met 60µs à écrire sur un port ? :/ Ce qui risque d'être gênant pour une boucle de 2µs ...)
J'ai encore du boulot pour arriver à quelque chose de correct :/ Je vais essayer d'augmenter encore la vitesse de l'ADC, mais ça dégrade les performances (au dessus de 15kHz) :/
EDIT : J'ai compris ce qui ne va pas avec l'écriture sur le port L : en même temps, je fais une division par 4, c'est ça qui prend du temps ! Ce qui est étrange, c'est que le compilo n'optimise pas cette ligne de code ! Une division par 4 revient à décaler le nombre de 2 bits sur la droite.
En remplaçant PORTL = sample/4; par PORTL = sample>>2; l'écriture sur le port devient instantané.
EDIT 2 : Et voilà, en mettant un prescale à 8 au lieu de 16 sur la clock de l'ADC et en utilisant un décalage de bits à la place de la division, j'arrive à échantillonner à 44.1kHz et à faire sortir le signal numérique sur le port L.
Au niveau du rendu sonore, ça marche bien. J'entend bien le morceau joué par mon lecteur MP3 sur le hautparleur, le signal étant passé entre deux par l'arduino

J'espère juste que les fonctions de traitements audio ne seront pas trop chronophages :/
Voilà le code qui marche (toujours en vrac).
#define FASTADC 1
// defines for setting and clearing register bits
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
int sample;
void setup() {
#if FASTADC
// set ADC prescale to 8
//*
cbi(ADCSRA,ADPS2) ; // 0
sbi(ADCSRA,ADPS1) ; // 1
sbi(ADCSRA,ADPS0) ; // 1
//*/
#endif
// Initialisation du port7 (arduino Mega : pin 42 à 49)
for(int i = 0; i < 8; i++) {
pinMode(42+i,OUTPUT);
}
//pinMode(13,OUTPUT);
DDRB = 0xFF;//all outputs
// Configuration du timer1.
// Interruption à 44.1kHz
noInterrupts();
TCCR1A = 0;// set entire TCCR0A register to 0
TCCR1B = 0;// same for TCCR0B
TCNT1 = 0;//initialize counter value to 0
OCR1A = 362;// = (16*10^6) / (44100) - 1 (must be <256) (44077Hz)
TCCR1B |= (1 << WGM12); // CTC
TCCR1B |= (1 << CS10); // prescale1
TIMSK1 |= (1 << OCIE1A); // timer compare interrupt enable
interrupts();
}
// Interruption timer 1
ISR(TIMER1_COMPA_vect){ //44.1kHz interrupt routine
//PORTB = PORTB ^ B10000000; // pour tester la fréquence à l'oscillo
sample = analogRead(0);
PORTL = sample>>2;
}
void loop(){
}