Interfaces analogiques
(ADC & DAC)
Arduino DUE
SÉMINAIRE DESIGN II,
A
RDUINO
DUE
¢
Atmel SAM3X8E Arm Cortex M3
32 bits
84 MHz
3.3 Volts ! Attention !!!
¢
11 Canaux d’ADC : AT06860
12 bits,
Jusqu’à 1MHz (mais 666 kHz à cause du 84 MHz)
¢ 84/6 = 14 MHz max clock de l’ADC
¢ 14 MHz / 21=666 kHz sampling rate
¢
2 Canaux de DAC
12 bits
Processeur Cortex M3 Compteurs ADC DAC PDC Peripheral DMA Controller Relié aux DAC & ADC RAM
U
TILISATION
SIMPLE
¢Mavaise idée !!
Vitesse limitée ¢ ~20kHz
Aucune garantie
¢ Fs ne sera pas constant
Bloque le flot d’exécution
void setup() {
// put your setup code here, to run once: analogWriteResolution(12);
analogReadResolution(12); // 10 is default
Serial.begin(9600); }
void loop() {
// put your main code here, to run repeatedly: uint16_t i =0;
analogWrite(DAC0,i);
Serial.print(analogRead(A0)); i++;
I
NTERUPTIONS
¢
Signal émis par du HW ou du SW pour signifier
qu’un évènement demande de l’attention
immédiate
L’état (registre, stack…) peut être sauvegardé
Le code est interrompu
La fonction d’interruption est appelée.
T
IMER
INTERUPTS
SUR
LE
DUE
¢
Les compteurs (timer counters)
On peut leur spécifier une horloge ¢ On peut diviser l’horloge de 84 MHz par:
¢ 2, 8, 32, 128
On leur spécifie jusqu’à combien compter
Vont générer une interruption HW lors que le
compteur déborde ¢
Exemple:
84 MHz / 2 = 42 MHz
Compter jusqu’à 1000
L
ES
COMPTEURS
¢
3 Modules de Compteurs
TC0, TC1, TC2
¢
Chaque compteur a 3 canaux
0, 1, 2
¢
9 Canaux au total
Chaque canal est un compteur et chaque a son
interupt et sa fonction de gestion d’interruption Numéro de l’IRQ
¢ 3*TC + canal
¢ Exemple TC1, canal 2
E
XEMPLE
I
NTERUPT
TC2,
CHAN
1 => #7
const int led_pin = 13;
int state = false;
void setup()
{
pinMode(led_pin, OUTPUT);
pmc_set_writeprotect(false); // power management control (pmc)
pmc_enable_periph_clk(ID_TC7); // Allumer le périphérique qui sera utilisé // Config le timer TC2, channel 1, TIMER_CLOCK4 == /128
TC_Configure(TC2,1, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK4); TC_SetRC(TC2, 1, 131200); // On compte jusqu’à 131200
TC_Start(TC2, 1); // Partir le timer // Faire en sorte que la fonction d’interruption est appelée
TC2->TC_CHANNEL[1].TC_IER=TC_IER_CPCS; // IER = interrupt enable register TC2->TC_CHANNEL[1].TC_IDR=~TC_IER_CPCS; // IDR = interrupt disable register NVIC_EnableIRQ(TC7_IRQn);
E
XEMPLE
I
NTERUPT
:
FONCTION
DE
GESTION
¢84MHz/128/131200 = 5 Hz (0.2 seconde)
TIMER_CLOCK1 == /2 , …, TIMER_CLOCK4 == /128 void loop(){ // Il ne se passe rien dans la boucle !!!
}
void TC7_Handler() {
TC_GetStatus(TC2, 1); // Efface le status et permet un nouvel appel de l’interrupt
state = !state;
digitalWrite(led_pin, state); // On fait juste clignoter une LED 5 fois par sec
I
NTERRUPTIONS
: P
ARFAIT
POUR
LE
DAC
¢
Générer la forme d’onde qui va contrôler le moteur
¢
DDS: Direct digital synthesis
Configurer un interrupt pour avoir le taux
d’échantillonage voulu.
Définir un tableau (array)
¢ Ex: un cycle d’une onde triangulaire
Jouer le tableau en boucle
¢ un échantillon à chaque passage dans la fonction de gestion
Ne pas utiliser: “analogWrite” Utiliser:
“dacc_write_conversion_data” Plus rapide
INTERUPTION
ET
ADC
¢
Acquérir le signal du photodétecteur
¢
On pourrait procéder de la même manière pour
l’ADC
Lire un échantillon à chaque interuption
¢
On aurait le problème de gérer l’interface série à
chaque interuption, pour transmettre un point
¢
Et/ou d’écrire du code pour regrouper les données
¢
On peut faire mieux avec le DMA.
DMA & ADC
¢
On peut configurer l’ADC pour échantillonner tout le
temps
C’est un périphérique indépendant du processeur
Les échantillons vont juste aller nulle part.
¢
On peut dire à l’ADC d’envoyer les échantillons
directement dans la RAM
Adresse du premier échantillon
Taille du tableau.
¢
Quand le tableau est plein, les échantillons se
perdent à nouveau
¢
Le processeur peut lire la RAM en temps opportun
S
TATÉGIE
: ADC
¢Dans setup()
Configurer l’ADC pour qu’il échantillonne au taux voulu
¢
Lorsqu’on est prêt
Passer l’adresse et la taille du bloc via le PDC
¢
Dans la boucle loop()
Gérer le contrôleur série et transmettre les données du
bloc lorsque l’ordinateur le demande.
S
YNCHRONISATION
DU
DAC
ET
DE
L
’ADC
¢
On veut partir l’acquisition quand le balayage
commence:
Configurer le DMA avec le PDC dans l’interrupt
utilisé pour le DAC
¢ À chaque fois qu’on passe à un endroit précis de la forme
d’onde
Forme d’onde générée par le DDS
Passer le tableau au DMA lorsqu’on est à cet endroit dans le cycle
N
OTES
¢
La programmation avec interuptions n’est pas
séquentielle
Comme le DMA est configuré dans l’interrupt
¢ Le tableau peut commencer à se remplir n’importe quand
¢ Peut importe où on est rendu dans la boucle loop()
¢
Bonnes pratiques
Sémaphores
Double buffer