Outils pour utilisateurs

Outils du site


tns_nucleo_tp1

homepages.laas.fr_bvandepo_files_iut_tp_pic_warning.jpeg A FAIRE A LA FIN DE CHAQUE SEANCE POUR COPIER VOS FICHIERS SUR UN DISQUE PARTAGE (ET PERMETTRE LA RECUPERATION DES FICHIERS SI UN MEMBRE DU BINOME EST ABSENT) copier coller dans une console:

rsync -av --delete ~/workspace_ac6 /mnt/etu/s4

et completer la ligne en appuyant 3 fois sur la touche Tabulation, puis entrée.

Objectifs du TP

  • Mettre en oeuvre les périphériques ADC, DAC, Timer
  • Générer un signal audio sur la sortie DAC de la carte
  • Capturer un signal audio sur l'entrée ADC de la carte

Les informations nécessaires au lancement de l'outil SystemWorkbench utilisé pour ce tp sont disponibles sur Mise en place du projet architecture pour le TNS sur plateforme Nucléo


Récupération du Projet C++ de départ

Fermer les outils eclipse et STM32CubeMX.

Récupération du projet de base en C++

Copier/coller dans une console:

echo commence
mv ~/workspace_ac6 ~/workspace_ac6_etu
cd ~/
mkdir -p ~/workspace_ac6
cd ~/workspace_ac6 
wget http://homepages.laas.fr/bvandepo/files/iut/tp_tns/nucleo_tns_etu2018.zip
echo fini

Ensuite:

  1. lancer eclipse via la console en tapant: /opt/STM32/SystemWorkbench/eclipse
  2. cliquer à gauche sur l'icone C/C++
  3. cliquer droit dans project Explorer→Import, puis General→Existing Projects into Workspace
  4. cliquer sur Next
  5. cocher Select archive file, puis cliquer sur Browse
  6. choisir /home/IUT/<login étudiant>/workspace_ac6/nucleo_tns_etu2018.zip
  7. cliquer sur Finish

Initialisation système de gestion de version

Seulement après avoir importé le projet depuis l'archive dans eclipse, saisir dans une console:

cd ~/workspace_ac6/
rm  nucleo_tns_etu2018.zip
cd ~/workspace_ac6/nucleo_tns/
git init
git add *
git commit -m'initial version'
gitk 

Exercice 1: Génération de la base de temps

Afin de valider le fonctionnement du timer, nous allons utiliser la fonction d'interruption mise en place lors du TD pour générer des signaux périodiques sur des broches (dont on mesurera le signal à l'oscilloscope) et sur une LED (dont on observera le clignotement). L'interruption timer doit survenir à la fréquence de 48kHz (arrondi au plus proche). Pour cela, il faut modifier la fonction static void MX_TIM1_Init(void) déjà mise en place par l'outils STM32CubeMX dans le fichier Src/tim.c

Vous devrez affecter une bonne valeur à htim1.Init.Period pour obtenir la fréquence demandée. Il s'agit de la valeur correspondant au nombre de cycle -1 de décomptage du timer (chargée dans le registre nommé ARR lors du TD précédent), le prédiviseur étant réglé sur un facteur 1. Vous avez effectué un tel calcul lors du TD précédent.

Il faut ensuite compléter la fonction d'interruption dans le fichier Src/main.c

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
   //Code executé à la fréquence d'interruption
}

Génération du signal sur la broche

Vous disposez de 2 connecteurs sur la face avant du circuit imprimé de la carte de sortie connectés aux sorties PB11 et PB12 du STM32. Ces broches vont être utilisées pour mesurer à l'aide d'un oscilloscope le temps passé dans différentes parties du programme. Dans un premier temps, vous allez générer un signal sur la broche PB11 qui sera à 1 pendant la durée d'exécution de la fonction d'interruption timer et à 0 le reste du temps. La figure suivante présente les différentes broches des connecteurs de la carte:

homepages.laas.fr_bvandepo_files_iut_tp_tns_tns_line_in.jpg

Les autres broches des connecteurs sont organisées tel que le montre le schéma suivant:

Pour générer le signal demandé, vous utiliserez la fonction void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState). La valeur pour l'argument GPIOx est GPIOB, et pour l'argument GPIO_Pin, la valeur est GPIO_PIN_11. Le troisième argument peut prendre la valeur GPIO_PIN_SET ou GPIO_PIN_RESET selon que l'on souhaite activer ou désactiver la sortie.

Une fois le code mis en place et compilé, il vous faut mesurer la fréquence et la durée à l'état haut du signal généré à l'oscilloscope pour valider le bon fonctionnement. ATTENTION :le signal généré est haute fréquence (par rapport à la fréquence analogique max de l'oscilloscope), il faut donc désactiver le filtrage HF dans le menu Mode/Coupling.

Une fois le fonctionnement validé par un enseignant, mettre à jour le suivi de version en saisissant dans une console:

echo commence
cd ~/workspace_ac6/nucleo_tns/
git commit -a -m'timer ok'
gitk &
echo fini

Pilotage de la LED

homepages.laas.fr_bvandepo_files_iut_tp_tns_bonus.jpg Vous devez maintenant faire clignoter la LED rouge présente sur la carte de sortie. Pour cela, à chaque 24000 exécutions de la fonction d'interruption, changer l'état de la broche pilotant la LED. Vous pourrez utiliser la fonction void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin). La valeur pour l'argument GPIOx est GPIOB, et pour l'argument GPIO_Pin, la valeur est GPIO_PIN_13.

Vérifier que la LED s'allume bien une fois par seconde.

Une fois le fonctionnement validé par un enseignant, mettre à jour le suivi de version en saisissant dans une console:

echo commence
cd ~/workspace_ac6/nucleo_tns/
git commit -a -m'led ok'
gitk &
echo fini

Exercice 2: Test du DAC

Pour observer le comportement du DAC, nous allons l'utiliser pour générer un signal sinusoïdal (480Hz). Pour cela il vous faut compléter la fonction d'interruption pour :

  • Piloter la sortie connectée à la broche PB11 et à la LED (déjà mis en place dans l'exercice précédent)
  • Déterminer la valeur de l'échantillon actuel du signal sinusoïdal à 480Hz
  • Ecrire l'échantillon sur le DAC
  • Piloter la sortie connectée à la broche PB11 (déjà mis en place dans l'exercice précédent)

Les fonctions de la librairies math (sin, cos, tan …) ne sont pas utilisables dans la fonction de gestion d'interruption timer du fait de leur lenteur. Il faut donc définir un tableau contenant les échantillons précalculés d'une période de la fonction sinus pour la fréquence demandée. Pour cela, compléter le code suivant (à coller où il faut …). Les échantillons ainsi générés doivent couvrir la dynamique du convertisseur DAC (0 < = échantillon < = 4095). Vous pourrez vous inspirer du code écrit lors du TP4 de TNS qui est rappelé ici :

Ecrivez d'abord l'expression mathématique de chaque signal
 Ex : signal(t)=A.sin(2Π.fo.t) + Vmoy
Déterminez alors la valeur du signal aux instants d'échantillonnages.
 Ex : signal(k.Tech)=A.sin(2Π.fo.k.Tech) + Vmoy
Créez ensuite un tableau de taille nbEch (qui dépend de la durée voulue. Ex : tmax=duree=kmax.Tech d’où
 kmax=duree.Fech) par signal et remplissez-le avec les valeurs pour chaque k
Ex :  nbEch = kmax+1
      double signal[nbEch]
      for(int k=0; k<nbEch; k++) signal[k]= ..................;
sin_tabbed.c
 #include <math.h>
 #define SAMPLING_RATE  ( 48000.0f)
 #define SIN_FREQ  ( 480.0f)
 #define SIN_AMP 2000.0f
 #define SIN_TAB_LENGTH ((unsigned int) (SAMPLING_RATE / SIN_FREQ)) //Taille du tableau pour une période du signal sinus
  uint32_t sin_tabbed[SIN_TAB_LENGTH];
  void init_sin_tabbed(){
	unsigned int k ;
	for(k = 0 ; k < SAMPLING_RATE/SIN_FREQ; k ++ ){
		sin_tabbed[k] = ???; //Compléter ici par le calcul de la valeur des échantillons
	}
  }

Cette fonction est à appeler une fois au bon endroit dans le code de la fonction main, avant le lancement du timer, afin d'éviter qu'une interruption timer ne survienne avant que le tableau soit initialisé:

//Insérez ici l'appel de votre fonction **init_sin_tabbed**
HAL_TIM_Base_Start_IT(&htim1); //Déjà mis en place
HAL_DAC_Start(&hdac2, DAC2_CHANNEL_1); //Déjà mis en place

Ainsi, le tableau “sin_tabbed” contient les échantillons à utiliser dans la fonction d'interruption.

La fonction à utiliser pour écrire sur la sortie du DAC est: HAL_StatusTypeDef HAL_DAC_SetValue(DAC_HandleTypeDef* hdac, uint32_t Channel, uint32_t Alignment, uint32_t Data);. Cette fonction écrit une valeur “Data” sur canal “Channel” du DAC “hdac” avec l'alignement “Alignement”. Utiliser comme valeur de premier argument DAC_HandleTypeDef* hdac configuré à &hdac2. Pour le canal du DAC utiliser DAC2_CHANNEL_1 et pour l'alignement 0.

Une fois le code complet, valider par la mesure à l'oscilloscope du signal généré. La mesure se fait sur la broche PA6 de la carte pour la sortie du DAC.

Mesurez aussi le nouveau temps d'exécution de la fonction d'interruption sur la boche PB11.

Une fois le fonctionnement validé par un enseignant, mettre à jour le suivi de version en saisissant dans une console:

echo commence
cd ~/workspace_ac6/nucleo_tns/
git commit -a -m'dac ok'
gitk &
echo fini

Exercice 3: Utilisation de l'ADC

L'ADC du micro-controleur s'utilise avec les fonctions suivantes :

HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef* hadc); // Lance la conversion 
HAL_StatusTypeDef HAL_ADC_Stop(ADC_HandleTypeDef* hadc); // Stoppe la conversion 
HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef* hadc, uint32_t Timeout); //Attend le résultat de la conversion, le deuxième paramètre permet de limiter le temps d'attente.
uint32_t HAL_ADC_GetValue(ADC_HandleTypeDef* had) //Lit le résultat de la conversion

Les valeurs possibles du paramètre de retour HAL_StatusTypeDef sont : HAL_OK , HAL_ERROR , HAL_BUSY et HAL_TIMEOUT.

A l'aide de ces fonctions, complétez la fonction appelée périodiquement : void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) pour :

  • Piloter la sortie connectée à la broche PB11 et à la LED (déjà mis en place dans l'exercice précédent)
  • Piloter la sortie connectée à la broche PB12 à l'état haut
  • Lancer une conversion sur l'ADC
  • Attendre la fin de la conversion (HAL_ADC_PollForConversion doit retourner HAL_OK)
  • Récupérer le résultat de la conversion
  • Stopper le convertisseur
  • Piloter la sortie connectée à la broche PB12 à l'état bas
  • Ecrire l'échantillon converti sur le DAC (recopie le signal d'entrée sur la sortie)
  • Piloter la sortie connectée à la broche PB11 (déjà mis en place dans l'exercice précédent)

Pour la valeur effective de l'argument ADC_HandleTypeDef* hadc des fonctions ADC, vous utiliserez la valeur &hadc1, par exemple : HAL_ADC_Start(&hadc1);

La broche PB12 qui est maintenant pilotée permet de visualiser le temps nécessaire à la conversion analogique/numérique des échantillons d'entrée.

Une fois le code mis en place il vous faut le tester. Pour ce test, la carte Nucléo est associée à deux cartes : LINE_IN, LINE_OUT pour adapter les niveaux et protéger l'entrée ADC du micro-controleur. L'adaptation en entrée applique un gain de 4.54 sur le signal mis en entrée et le centre sur 1.65v.

La procédure de test est la suivante :

  1. configurez le canal génération de signal de l'oscilloscope pour une sinusoide à 400Hz centrée sur 0 avec une amplitude réglée pour ne pas saturer l'amplificateur de la carte LINE_IN (vcc=3.3v).
  2. vérifiez les caractéristiques du signal avec l'oscilloscope
  3. branchez la sortie du générateur de signaux sur l'entrée A0 de la carte d'adaptation LINE_IN
  4. branchez l'entrée de l'oscilloscope sur la sortie A1 de la carte d'adaptation LINE_OUT

img_20170327_130651.jpg img_20170327_130710.jpg

Vérifiez:

  1. la recopie du signal d'entrée sur la sortie
  2. sur la broche PB12, mesurez le temps temps nécessaire à l'ADC pour effectuer une conversion.
  3. sur la broche PB11, mesurez le temps total d'exécution de la fonction d'interruption.

Une fois le fonctionnement validé par un enseignant, mettre à jour le suivi de version en saisissant dans une console:

echo commence
cd ~/workspace_ac6/nucleo_tns/
git commit -a -m'adc ok'
gitk &
echo fini

Vous pouvez maintenant passer au TP suivant dans lequel vous allez insérer le filtre dans le programme du microcontroleur: tns_nucleo_filtre

tns_nucleo_tp1.txt · Dernière modification: 2018/04/04 20:15 par bvandepo