Résolution d’un problème numérique sur un composant fortement non-linéaire dans LTspice

Comme dans le post précédent, nous utilisons un « Voltage Controlled Switch » pour charger un condensateur, puis ouvrir le circuit. Nous allons prendre cet exemple pour illustrer un problème de simulation avec un composant fortement non linéaire.

Voici le circuit:

Le schéma LTspice est disponible ici

Nous avons volontairement choisi des valeurs de Ron très petite et Roff très grande.

Ci-dessous, avant t=1s, le circuit est fermé (Ron=0.0001 Ω), car la tension du sw (en rouge) est supérieure à 1V. La capa est chargée. A t=1s exactement, la résistance du switch passe brutalement de Ron=0.0001 Ω à Roff = 1M Ω. Le rapport Roff/Ron est très grand (1e+10).

La tension aux bornes du condensateur (en vert) chute lorsque que le commutateur passe de Ron à Roff, ce qui n’est pas logique.

C’est un problème de simulation. Le comportement du switch est instantané donc fortement non linéaire (voir tolerance on errors, en Anglais).

Si une large gamme de résistance ON à OFF doit être utilisée dans les interrupteurs (ROFF/RON >1e;+12), alors la tolérance sur les erreurs permises pendant l’analyse des transitoires doit être réduite en utilisant la ligne de contrôle .OPTIONS et en spécifiant que TRTOL est inférieur à la valeur par défaut de 7.0. Lorsque des interrupteurs sont placés autour des condensateurs, l’option CHGTOL doit également être réduite. Les valeurs suggérées pour ces deux options sont respectivement 1.0 et 1e-16. Ces changements incitent SPICE3 à être plus prudent autour des points de commutation afin qu’aucune erreur ne soit commise en raison de la modification rapide du circuit.

La solution consiste à ajouter la directive « .options trtol=0.001 » dans le schéma LTspice :

On peut aussi changer dans le « control Panel » -> « Spice », la valeur de TrTol de 1 à 0.001. C’est une solution « moins propre ».

Nous lançons la simulation :

Miracle, les choses s’arrangent!

En fait, je n’ai pas une compréhension réelle des paramètres de simulation. Je suis arrivé à cette solution grâce à la page web sus-citée et en cherchant « la bonne valeur » de Trtol (et ChgTol) en tâtonnant.

Et voilà!

Charge et décharge d’un condensateur avec un « Voltage Controlled Switch »

Mes deux posts sur LTspice ont eu du succès. J’ai décidé d’en faire un troisième, assez long. J’en profite pour faire de la pub sur d’autres articles de mon blog concernant des sujets tout aussi passionnants comme TensorFlow ou encore la BeagleBone Black (qui est vachement moins connue, je l’admets, mais c’est de la balle!). Surtout, n’hésitez pas à laisser des commentaires !!!

Problématique

Voilà le problème, qui m’a été soumis par mon beau-père, il y a déjà fort fort longtemps, du temps où j’étais jeune quoi.
Chargeons un condensateur dans un premier temps par une alimentation continue. Dans un second temps nous « débranchons » la source de tension et nous mettons un second condensateur, vide, en parallèle. Pas d’autre composant. Quelle sera alors la tension aux bornes des deux condensateurs?

Mon intuition me dit que la tension sera divisée par 2 puisque la charge sera répartie entre les deux capas. Si on note U la tension initiale du premier condensateur chargé et Uf la tension finale en régime stationnaire. Est-ce qu’on a Uf = U/2?

D’un autre côté, l’énergie stockée dans un condensateur est de 1/2 C U*U (voir ici pour le calcul de l’énergie). Si on note C1 la valeur du condensateur qu’on charge au début et C2 celui qui est déchargé. L’énergie avant de fermer le circuit est de :
Après, en « régime stationnaire », l’énergie sera répartie sur les deux capas :
où Uf est la tension finale que nous voulons calculer. Comme il n’y a pas de résistance dans le circuit, l’énergie est conservée :
Si les capas sont égales C1  = C2 = C, on  obtient On en déduit que la tension finale sera égale à la tension initiale divisée par la racine carrée de 2. Et cela quelque soit la capacité (égale) des condensateurs. Étonnant non?

Voyons ça dans LTspice.
Dans une première partie, nous allons nous familiariser avec le composant « Voltage Controlled Switch » qui permet de simuler un interrupteur.
Dans la seconde partie, nous étudierons le problème posé – en utilisant 2 composants « Voltage Controlled Switch ».

Partie I : « Voltage Controlled Switch » dans un circuit RC

Pour simuler ce truc, nous allons avoir besoin d’interrupteurs, un pour ouvrir le circuit de charge et un second pour fermer le circuit capacitif.

Or, il n’existe pas d’interrupteur simple dans LTspice et cela paraît logique parce c’est de la simulation, l’interrupteur est soit dans une position, soit dans une autre, mais une unique position par simulation. Pour commuter automatiquement, il faut adopter une autre stratégie.
Nous allons utiliser un composant appelé « Voltage Controlled Switch ». Voir discussion créer un interrupteur LTpsice.

Dans un premier temps, nous allons étudier un circuit RC simple et y ajouter un composant sw « Voltage Controlled Switch ». Ce composant sw a une résistance qui peut « switcher » entre deux valeurs en fonction d’une tension et d’un seuil. En fixant la résistance à une valeur faible (< 1 Ω) dans un cas et à une valeur grande dans l’autre cas (> 1 M Ω, voire plus), cela permet de simuler un interrupteur, contrôlé par une tension externe. En fait, il va y avoir un circuit principal (RC dans ce cas) et un second circuit avec une unique source de tension (composant « voltage »). Celui-ci pilote l’interrupteur (switch) .

Noter qu’il existe le même type de composant contrôlé en courant « Current Controlled Switch » csw, mais nous n’en parlerons pas dans ce post.

Le composant sw « Voltage Controlled Switch »

Dans un circuit RC, on introduit le composant sw:

En faisant un clic droit sur le composant sw, j’ai mis la valeur « value » à « monSW ». Il nous faut ajouter trois choses :

  1. une source de tension pour piloter pour le sw
  2. une directive pour spécifier les résistances du composant sw et la tension seuil
  3. le temps d’étude en régime transitoire (run, transient)

On ajoute une « spice directive », qu’on trouve soit sur la barre d’outil, soit dans l’onglet « édition » -> « Spice directive ». On ajoute la directive .model monSW SW(Ron=1 Roff=1Meg Vt=1 Vh=0). Cela signifie que le composant que j’ai renommé monSW à une tension seuil Vt de 1V – une tension d’hystérésis Vh de 0V, c-a-d que le seuil de déclenchement est le même en diminuant ou en augmentant la tension de commande – une résistance Ron de 1 Ω si la tension externe est supérieure à Vt et une résistance de 1 M Ω  si la tension est inférieure à Vt . Du coup, si la tension est supérieure à 1 V, le circuit est fermé et sinon le circuit est considéré comme ouvert. On peut ajuster Ron et Roff si bessoin Voir ici pour plus d’information (en Anglais).

Ensuite, on règle la tension de commande. Click droit sur le composant voltage entouré en rouge dans la figure ci-dessus et puis on clique sur « advanced »

 

On choisit/coche PWL(t1 v1 t2 v2) à gauche et pour t=0 on met 2V et pour t=2 (secondes) on met 0V.  La tension va passer linéairement de 2V à 0V en 2 secondes.

Du coup, la résistance au départ est de 1 Ω et la tension va passer en dessous de 1V à t= 1 seconde et ouvrir le circuit (1 M Ω).

Reste à cliquer sur le petit bonhomme qui court dans la barre à outils, ou aller dans l’onglet « simulate » puis « run ». Une fenêtre s’ouvre et on met 3 secondes pour le « Stop time »  et on coche la case « Start external DC supply voltages at 0V » ça nous donne la directive suivante: « .tran 3 startup ».

Au final, le circuit est:

On trace les courbes. En bleu, la tension « de commande ». En vert, la tension aux bornes du condensateur.

La courbe en bleu passe en dessous de 1V au temps t= 1 seconde. Donc avant 1 s, le circuit est fermé et la tension aux bornes de la capa est de 5V. Quand le circuit est ouvert, à partir de 1 seconde, le condensateur se décharge dans la résistance.
Du fait que le produit RC=0.1, la tension est divisée par 10 en 0.23 secondes. Et donc, la tension aux bornes de la capa est de 0.5 V à t=1.23 s.

Le fichier LTspice du circuit est disponible ici.

Partie II : charge d’un condensateur et circuit purement capacitif

Les étapes de construction du circuit sont moins détaillées que dans la première partie.

On met d'abord en place un circuit purement capacitif avec un switch en série..
On met en place le premier interrupteur de manière similaire à la partie I, avec une source de tension pour le piloter.
Même réglage de la tension qui pilote interrupteur que dans la partie I : l'interrupteur s'ouvre à t=1 sec.
Figure ci-dessous: ajout d'une seconde capa et d'un second interrupteur pour connecter les deux condensateurs ensemble à t=3 secondes.
Réglage de la tension qui pilote le second interrupteur: 0V pendant 2 sec puis 2V à 4 sec, linéaire. Ainsi le seuil 1V est dépassé à 3 sec, l'interrupteur numéro 2 se ferme.

Une fois les deux générateurs de tension qui pilotent les interrupteurs réglés:

Finalisation du circuit: les directives spice pour les « Voltage Controlled Switches ».
On a utilisé le même modèle pour les deux interrupteurs (monSW1 et monSW2). Les directives « .model monSW1 SW(…) » et « .model monSW2 SW(…) » sont identiques: une résistance Ron à 1 Ω et Roff à 100 M Ω et une tension seuil de 1 Volt.

Circuit final:

Le fichier LTspice du circuit est disponible ici.

Le hic!!!

Ci-dessous les courbes: en vert la tension aux bornes de C1 et en bleu la tension aux bornes de C2. En marron, la ligne constante à 1V. Au départ, Le condensateur 1 est très rapidement chargé. Le premier interrupteur s’ouvre à t=1s et le second interrupteur se ferme à t=3s.

Le premier switch s’ouvre à t=1 seconde, car la courbe bleu claire passe en dessous de 1V et le second switch se ferme à t=3 secondes, car la courbe rouge passe au-dessus de 1V.

La tension aux bornes des 2 capas est : 2.5 Volts, soit U/2 et non pas U/racine(2).

Explication possible

La charge électrique q d’un condenseur s’écrit : q = C U.
Lorsqu’on met les deux condensateurs en parallèle, la charge électrique reste la même, mais la capacité C est multiplié par deux. Par conséquent, la tension est divisée par deux: q = C U = 2C U/2.

Vraiment bizarre!!!!

Liens utiles:
tutoriel pour apprendre à utiliser LTspice
Les raccourcis clavier
changer la taille des lignes et des caractères sur les figures (en Anglais)
cours sur les condensateurs
créer un interrupteur sous LTspice (discussion)

Les entrées analogiques de la Beaglebone Black, ARM et PRUs

L’objectif ici est de compiler et d’exécuter un programme permettant de lire une tension sur des pins analogiques. Deux programmes, en fait, l’un côté PRU (Programmable Real-time Unit) et l’autre côte CPU ARM. Finalement, j’ai opté pour les exemples fournis par Texas Instruments, qui est le constructeur du « cœur » (SoC AM3358/9) de la BBB. Au départ, je ne saisissais pas bien comment lancer les programmes fournis par TI, ni l’intérêt exact du SDK. J’ai en plus installé leur « Code Composer Studio » sur ma bécane (CCS), qui prend moultes Giga et est bien complexe. Je vais probablement le désinstaller.
Grâce au projet BeagleScope, dont je parle dans mon précédant post,  en étudiant le fichier deplay.sh, j’ai compris comment lancer un programme (dans le firmware) sur l’un des deux micro-contrôleurs (les fameux PRUs).

Le premier exemple, dans le post précédent, consistait à faire clignoter une LED à partir d’un pin numérique configuré en « output ». Maintenant, nous allons construire et exécuter un projet, nommé « PRU_ADC_onChip » qui  a pour objectif de lire des valeurs sur des pins analogiques (ADC = Analog to Digital Converter) et de les convertir en Volts en fonction d’une tension de référence. Les ADC de la BBB ont 12 bits de résolution et prennent donc des valeurs entre 0 et 4096-1 (4096 = 2 puissance 12). La tension de référence pour les convertisseurs est de 1.8 V, au lieu des 3.3 V pour pour les pins numériques. ATTENTION, ne pas mettre une tension supérieure à 1.8 V au risque d’endommager laBeagleBone! La tension de référence est fournie sur le pin P9_32 (VDD_ADC) et une terre analogique sur le pin P9_34 (GROUNDA_ADC). Vraiment, faite attention de ne pas mettre une tension supérieure à 1.8 V dans les entrées analogiques, please!!!
Les pins d’entrée analogique, sur le header P9, sont numérotées de AIN0 à AIN6 (7 entrées), pins 33 et 35 à 40, le pin 34 étant la terre et le pin 32 étant la référence à 1.8 V.  Les entrées analogiques sont surlignées en vert dans la figure ci-dessous:

Une vidéo illustrant le « projet », dans ses grandes lignes, est disponible ici : How to Use the PRU to Control a Peripheral: PRU_ADC_onChip on Sitara 335x using Beaglebone Black. C’est une bonne idée de la regarder cette vidéo, elle ne dure que 10 minutes (si l’Anglais ne vous rebute pas).

Les explications dans ce post sont certainement transposables à d’autres BeagleBones (Green, Blue), moyennant quelques adaptations.
Note: la résolution est ici de 12 bits, contre 10 bits pour l’Arduino Uno. La résolution standard d’un fichier audio est de 16 bits (signé).
Du coup, cela signifie que le pas de quantification est de 1.8 V divisé par (2 puissance 12, moins 1), soit 0.440 mV environ!

Résumé avec la vidéo TI (traduction) :

Dans certaines situations, il est plus logique de contrôler un périphérique avec un processeur déterministe dédié plutôt qu’avec un cœur ARM à usage général dans un processeur TI. Les applications vont d’un système de surveillance dédié où la charge de traitement peut être déchargée de l’ARM à un environnement en temps réel où le stimulus nécessite une réponse du processeur dans un laps de temps connu. Cette vidéo fournit un exemple d’utilisation du noyau d’unité programmable en temps réel (PRU) pour contrôler un périphérique sur n’importe quel processeur TI avec un PRU-ICSS ou PRU_ICSSG. Dans ce cas, pour contrôler le convertisseur analogique-numérique (ADC) sur le processeur Sitara AM335x à l’aide du BeagleBone Black.

Sur le projet PRU_ADC_onChip :

Il s’agit d’un projet de référence pour l’utilisation du PRU-ICSS pour contrôler un périphérique ADC sur l’AM335x. Le but de ce projet est de fournir un modèle pour contrôler un périphérique sur puce à l’aide du PRU. Il démontre également une application de RPMsg pour la communication ARM-PRU.

Nous allons passer aux choses sérieuses, à savoir la compilation des deux codes, l’un sur la BBB pour le PRU et l’autre sur votre PC sous Linux pour le processeur ARM de la BBB.

La première étape consiste à modifier le fichier /boot/uEnv.txt, puis rebooter.
Dans ce fichier de configuration, il faut dé-commenter la ligne suivante :
disable_uboot_overlay_adc=1, afin d’empêcher le processeur ARM d’accéder à la conversion analogique numérique ADC, car ce sera la tâche du micro-contrôleur.
Re-booter :
sudo reboot now

La seconde étape: le projet fait partie du pru-software-support-package fourni par Texas Instruments (TI) et téléchargeable ici pru-software-support-package. Il est souhaitable de le télécharger sur votre PC, puis de le copier sur votre BBB :
scp pru-software-support-package-5.6.0.zip debian@beaglebone.home:/home/debian/
Sur les deux ordinateurs (PC et BBB), le décompresser :
unzip pru-software-support-package-5.6.0.zip
Le projet s’appelle PRU_ADC_onChip et se trouve dans le répertoire :  pru-software-support-package-5.6.0/examples/am335x/PRU_ADC_onChip.

La troisième étape (1/2) : installation du SDK sur le PC pour la compilation croisée.
On trouve le SDK de TI depuis PROCESSOR-SDK-AM335X, c’est un très gros fichier  « ti-processor-sdk-linux-am335x-evm-06.03.00.106-Linux-x86-Install.bin » (9.2 Go après installation, sur mon PC) . Une fois téléchargé, il faut l’exécuter pour installer le SDK :
chmod u+x ti-processor-sdk-linux-am335x-evm-06.03.00.106-Linux-x86-Install.bin
./ti-processor-sdk-linux-am335x-evm-06.03.00.106-Linux-x86-Install.bin


La troisième étape (2/2) : la compilation croisée (cross-compilation)
Il s’agit de compiler le programme depuis le PC (processeur x86) pour le processeur ARM de la BeagleBone, sur lequel il sera exécuté.
Le code source est dans le fichier pru_adc_userspace.c, qui se trouve dans le sous répertoire PRU_ADC_onChip/pru_adc_userspace
Attention, celui-ci doit être compilé sur votre PC.
Ce n’est pas indiqué explicitement dans le README.txt, mais c’est nécessaire.
Faire l’export suivant pour le dossier bin du SDK :
export ARM_CCT=/home/benaroya/ti-processor-sdk-linux-am335x-evm-06.01.00.08/linux-devkit/sysroots/x86_64-arago-linux/usr/bin
en remplaçant « /home/benaroya » par votre répertoire racine contenant le SDK
Dans le répertoire PRU_ADC_onChip/pru_adc_userspace, on compile :
make clean
make

Enfin, il ne reste plus qu’à recopier le dossier généré « gen » vers l’exemple sur la BeagleBone
scp -r gen debian@beaglebone.home:/home/debian/pru-software-support-package-5.6.0/examples/am335x/PRU_ADC_onChip/pru_adc_userspace/

La quatrième étape : compilation pour le PRU 0 sur la BBB.
dans PRU_ADC_onChip, compiler pru_adc_firmware.c dans la beaglebone :
export PRU_CGT=/usr/share/ti/cgt-pru
make clean
make

Vous pouvez insérer l’export dans ~/.bashrc, pour ne plus le faire à chaque connexion à la BBB.

La cinquième étape : démarrer le PRU.
Comme indiqué dans le post précédent, il faut mettre le code pour le PRU 0 dans le firmware et lancer le remoteproc0. Il y a une erreur dans le programme fourni par TI parce que  pru_adc_userspace.c essayez de lancer automatiquement PRU 1, alors que le programme « pru_adc_firmware.c » est compilé avec des options pour le PRU 0. ça n’a pas fonctionné en l’état chez moi.

Dans pru_adc_firmware.c :
/*
* The PRU-ICSS system events used for RPMsg are defined in the Linux devicetree
* PRU0 uses system event 16 (To ARM) and 17 (From ARM)
* PRU1 uses system event 18 (To ARM) and 19 (From ARM)
*/
#define TO_ARM_HOST 16
#define FROM_ARM_HOST 17

Dans pru_adc_userspace.c :
char firmware[] = "/sys/class/remoteproc/remoteproc1/firmware";
char pruState[] = "/sys/class/remoteproc/remoteproc1/state";

Remplacer remoteproc1 par remoteproc0 ne suffit pas bizarrement.

On revient à nos moutons: renommer et copier le code compilé dans le firmware,
cp PRU_ADC_onChip.out PRU_ADC_onChip-fw
sudo cp PRU_ADC_onChip-fw /lib/firmware/

et démarrer le programme sur le PRU 0
echo 'stop' > /sys/class/remoteproc/remoteproc0/state 2>/dev/null
echo "PRU_ADC_onChip-fw" > /sys/class/remoteproc/remoteproc0/firmware
echo 'start' > /sys/class/remoteproc/remoteproc0/state

Dernière étape : tester
./gen/pru_adc_userspace -c 5
Reading voltage at ADC Channel: 5
Voltage on ADC Channel 5 is 1.7960V
./gen/pru_adc_userspace -c 6
Reading voltage at ADC Channel: 6
Voltage on ADC Channel 6 is 0.9270V
./gen/pru_adc_userspace -c 7
Reading voltage at ADC Channel: 7
Voltage on ADC Channel 7 is 0.0501V

C’est magnifique, car physiquement, le pin AIN4 (canal 5) est rélié à l’analog VDD (1.8 V), le pin AIN5 (canal 6) est « au milieu » (pont résistif de 2k Ohms) et le pin AIN6 (canal 7) est à la masse. Cependant, c’est un peu fluctuant au cours du temps. Apparemment, il y a moyen de moyenner la mesure:
/*
* set the ADC_TSC STEPCONFIG1 register for channel 5
* Mode = 0; SW enabled, one-shot
* Averaging = 0x3; 8 sample average
* SEL_INP_SWC_3_0 = 0x4 = Channel 5
* SEL_INM_SWC_3_0 = 1xxx = VREFN (reduces noise in single ended mode)
* use FIFO0
*/
ADC_TSC.STEPCONFIG1_bit.MODE = 0;
ADC_TSC.STEPCONFIG1_bit.AVERAGING = 3;
ADC_TSC.STEPCONFIG1_bit.SEL_INP_SWC_3_0 = 4;
ADC_TSC.STEPCONFIG1_bit.SEL_INM_SWC_3_0 = 8;
ADC_TSC.STEPCONFIG1_bit.FIFO_SELECT = 0;

Discussion générale :
Nous avons compilé et testé ce projet pour la lecture d’une entrée analogique. Il est composé de deux codes, l’un pour le PRU 0 qui va lire une valeur sur un pin analogique. Cette partie du code est assez lisible. Ensuite, cette valeur (échantillonnée sur 12 bits) est envoyée au micro-processeur ARM. La communication entre PRU et ARM est assurée par le framework RPMsg (Remote Processor Messaging, voir peut-être ici). Ne connaissant pas ce framework, je vais me rencarder sur ce Graal.
Enfin, le second code, compilé sur mon PC , est exécuté sur la BBB par l’ARM. Celui-ci envoie une requête avec le numéro du canal et reçoit en retour la valeur mesurée. Enfin, celle-ci est convertie en Volts et affichée.

Conclusion :
Nous avons abordé, entre autres, le téléchargement du « pru-software-support-package » de Texas Instruments, l’installation du SDK sur le PC, la compilation des deux codes, l’activation du PRU et enfin nous avons fourni de bons résultats de l’exécution du programme sur ARM.
A noter que le PRU lit une seule valeur sur l’ADC  (one-shot). Il serait intéressant de lire des valeurs à intervalles réguliers et de les renvoyer à l’ARM. Aussi comprendre la communication entre PRU et ARM avec le RPMsg.

Et Voilà !!!

Programmer les « Programmable Real-time Units » de la BeagleBone Black (PRUs)

Dans ce post, on va apprendre à faire clignoter une LED avec le microcontrôleur PRU 0 (il y en a deux). L’objectif est d’apprendre à lancer un programme en C dans le micro-contrôleur. Après on peut modifier le programme pour faire un tas d’autres choses. C’est une base.
PRU signifie « Programmable Real-time Unit ».

J’ai perso eu du mal à démarrer avec les PRUs dans ma BeagleBone Black . Beaucoup de documents sur le net. Mais beaucoup utilisent les « tree obverlays » et les slots qui eux n’existent plus dans les versions récentes de la BBB. J’ai fini par faire clignoter ma LED après trois soirées de boulot. C’est frustrant, mais maintenant j’ai à peu près compris la logique. C’est ce que j’expose ici, en espèrant que ça vous sera utile!

Mon approche est basée sur Remoteproc, qui signifie « remote processor », c-a-d processeur distant. C’est une approche, récente, pour programmer les PRUs. Il y en a trois: remoteproc0, remoteproc1, remoteproc2. Comme on le voit ci-dessous, remoteproc2 est occupé. Les deux autres sont utilisables et correspondent aux PRU 0 et 1.

Pour bien commencer, lancer une connexion ssh dans un terminal
ssh debian@beaglebone.home

Dans le log au démarrage:
dmesg | tail -100
[ 11.957862] remoteproc remoteproc0: 4a334000.pru is available
[ 11.958057] pru-rproc 4a334000.pru: PRU rproc node pru@4a334000 probed successfully
[ 11.973707] remoteproc remoteproc1: 4a338000.pru is available
[ 11.973893] pru-rproc 4a338000.pru: PRU rproc node pru@4a338000 probed successfully

[ 61.264026] remoteproc remoteproc2: wkup_m3 is available
[ 61.271194] remoteproc remoteproc2: powering up wkup_m3
[ 61.271222] remoteproc remoteproc2: Booting fw image am335x-pm-firmware.elf, size 217168
[ 61.275721] remoteproc remoteproc2: remote processor wkup_m3 is now up

Editer et Modifier/boot/uEnv.txt pour désactiver la fonction HDMI.
###Disable auto loading of virtual capes (emmc/video/wireless/adc).
disable_uboot_overlay_video=1
disable_uboot_overlay_audio=1
Puis re-démarrer: sudo reboot now
Attention, c’est utile (uniquement) si on doit utiliser les pins du header P8 qui sont partagés avec l’HDMI. Voir les liens vers des tableaux « PinMux modes » en fin de post.

Information sur ma configuration :
ma disto
cat /etc/dogtag
BeagleBoard.org Debian Buster IoT Image 2020-04-06
cat /etc/debian_version
10.3
uname -a
Linux beaglebone 4.19.94-ti-r42 #1buster SMP PREEMPT Tue Mar 31 19:38:29 UTC 2020 armv7l GNU/Linux

Commençons les choses sérieuses

Télécharger BeagleScope (licence GPL v2), qui nous fourni les includes et libs pour pouvoir compiler et faire l’édition de lien, avec le Makefile.
git clone https://github.com/ZeekHuge/BeagleScope.git
si besoin, installer git : sudo apt-get install git
cd BeagleScope/
cd examples/firmware_exmples/pru_blinky/

Il y a des erreurs dans deploy.sh, on va faire le boulot en ligne de commande.
cd PRU_gpioToggle

Remplacer le fichier PRU_gpioToggle.c par celui sur ma page perso (avec wget, ci-dessous). Le code active le pin 27 du P9 (pin P9_27).
mv PRU_gpioToggle.c PRU_gpioToggle.c.old
wget elaurent.benaroya.free.fr/wordpress/BBB/PRU_gpioToggle.c

Vous pouvez (devez) éditer ce code. Ce qui est à retenir :

Le registre R30 est utilisé pour mettre à l’état haut ou l’état bas un pin configuré en sortie (pruout).
C’est un registre 32 bits.
On met alternativement le bit numéro 5 à 1 (état haut) et à 0 (état bas).
Le bit 5 du registre R30 correspond physiquement à P9_27.
Après avoir changé la valeur du bit 5 dans R30, on attend avec la fonction __delay_cycles pendant 100 millions de cycles, soit 1/2 secondes car le micro-controlleur fonctionne à 200 MHz.
Enfin, on boucle 60*5 fois, c’est dire pendant 5 minutes.
Ensuite, la commande __halt(); arrête le processus.

Attention, l’inclusion du fichier resource_table_empty.h est importante bien que celui-ci ne fasse pas grand chose.
Note importante : le code que je fournis est adapté de celui : beaglebone-pru-c

Compilation

1) d’abord définir la variable d’environnement PRU_CGT:
Créer les liens symboliques, à ne faire qu’une seule fois!
sudo ln -s /usr/bin/clpru /usr/share/ti/cgt-pru/bin/clpru
sudo ln -s /usr/bin/lnkpru /usr/share/ti/cgt-pru/bin/lnkpr

Puis :
export PRU_CGT=/usr/share/ti/cgt-pru
L’export peut être placé dans votre ~/.bashrc pour ne pas avoir à s’en occuper à chaque connexion au BBB.

2) Compiler
make clean
make

3) Copier le binaire dans le firmware
cd gen
cp PRU_gpioToggle.out gpiotoggle-fw
sudo cp gpiotoggle-fw /lib/firmware

Note importante : dans les versions « anciennes » du système d’exploitation, le nom du programme chargé dans le firmware est fixé : « am335x-pru0-fw » pour le PRU0 et « am335x-pru1-fw » pour le PRU1. Il faut donc remplacer la commande ci-dessous par :
cd gen
cp PRU_gpioToggle.out am335x-pru0-fw
sudo cp am335x-pru0-fw /lib/firmware

Le schéma électronique consiste à placer une LED et une résistance de 500 ohms environ, en série, entre P9_27 et P9_1 (DGND, digital ground).
Utiliser une LED jaune, rouge ou orange du fait de la chute de tension (entre 2 et 2.8 V contre 3.2 V au moins pour une bleue), sachant que la tension de sortie des gpio est de 3.3V!

Avec un résistance de 500 ohms, on obtient environ un courant de (3.3-2.3)/500 = 2 mA. C’est acceptable. Attention, le courant maximum délivré par chaque pin du gpio est de l’ordre de 4 mA à 8 mA, selon le pin : voir discussion dans GPIO current capacity?. C’est beaucoup moins qu’un Arduino, attention!!!

Configurer le pin P9_27 en sortie digitale (pruout)
config-pin

GPIO Pin Configurator
Usage:
   config-pin -c <filename>
   config-pin -l <pin>
   config-pin -q <pin>
   config-pin <pin> <mode>

config-pin -l P9.27
Available modes for P9_27 are: default gpio gpio_pu gpio_pd gpio_input qep pruout pruin
config-pin -q P9.27
Current mode for P9_27 is: default
config-pin P9.27 pruout
Current mode for P9_27 is: pruout

Lancer le programme sur le PRU0 (remoteproc0)
echo 'stop' > /sys/class/remoteproc/remoteproc0/state 2>/dev/null
echo "gpiotoggle-fw" > /sys/class/remoteproc/remoteproc0/firmware
echo 'start' > /sys/class/remoteproc/remoteproc0/state

La LED devrait se mettre à clignoter pendant 5 minutes.
Pour vérifier que les trois commandes ci-dessus se sont bien passées, on peut faire un dmesg. Si erreurs, problème!
dmesg | tail
[ 3105.812064] remoteproc remoteproc0: powering up 4a334000.pru
[ 3105.812358] remoteproc remoteproc0: Booting fw image gpiotoggle-fw, size 33556
[ 3105.812391] remoteproc remoteproc0: remote processor 4a334000.pru is now up
Note : comme indiqué ci-dessus, dans les versions plus anciennes de l’OS, le nom du programme dans le firmware est fixé,  la commande convenable est donc :
echo "am335x-pru0-fw" > /sys/class/remoteproc/remoteproc0/firmware

Approfondissement et liens externes

Pour le plaisir de mettre une image des headers P8 et P9 (c’est vendeur) :

Beaglebone Black Headers PinMux Modes

Les tableaux PinMux modes pour les headers P8 et P9
Celui-ci est très bien BeagleboneBlackPinMuxModes et les versions imprimables en pdf: P8 : P8 headers pdf et P9 : P9 headers pdf.
Dans la table du header P9, on a

P9 pin Offset mode 5 mode 6
P9_27 0x9A4 pr1_pru0_pru_r30_5 pr1_pru0_pru_r31_5

Dans cet extrait de la table, le pin 27 du header P9 correspond à pr1_pru0_pru_r30_5, qui indique le PRU 0, le registre 30 (output) sur le bit no 5.
Le mode 6, c’est la même chose mais en input, sur le registre R31. J’écris le bit no 5 parce que la numérotation des bits dans un nombre, en binaire, commence à 0. Donc le pin no 5 à 1 correspond à 0b0010_0000 en écriture binaire (sur 8 bits). En langage C, ce nombre peut s’écire 1 << 5 .

Voici un autre tableau équivalent, avec stabilotage : P9 headers.

Les pins GPIO pour la BeagleBone Black physiquement : The BeagleBone Black GPIO Pins ou gpio très complet (les figures en bas de la page).

Programmation des PRUs en C

Technique et bas niveau, mais vraiment intéressant, codage en C pour les PRUs : Beaglebone PRU Code in C

Sur les Remoteproc Remoteproc wiki

Super projet, proche de ce que je veux faire et qui a pour but d’acquérir de l’audio par le PRU, en temps réel, et de le transmettre au CPU qui le traite ou le joue : Using the Beaglebone Green Programmable Real-Time Unit with the RemoteProc and Remote Messaging Framework to Capture and Play Data from an ADC, lien parent du repo github.

Note sur le temps-réel

Il est important de comprendre que les PRUs permettent des traitements temps réel, car ce sont des micro-controlleurs dont on maîtrise totalement le fonctionnement en particulier celui des interruptions. Les versions « standards » de Linux ne permettent pas le temps réel parce qu’il peut se passer plein de trucs externes pendant l’exécution d’un programme. Il ne faut pas confondre temps réel et faible latence. Temps réel signifie qu’on peut prédire le temps d’excution d’un programme – de manière déterministe – indépendemment de la latence.

L’incontournable zeekhuge

Ce lien suivant est assez proche ce que j’ai exposé : l’application « blinky » : ptp_blinky. C’est assez complémentaire en fait.
Concernant les PRUs en général : working_with_prus_beagleboneblack_introduction_to_prus.

Conclusion

Dans ce post, j’ai exposé en détail comment compiler et exécuter un programme sur une « Programmable Real-time Unit » (PRU) de la BeagleBone Black. Le programme fait simplement clignoter une LED. J’espère que cette introduction à la programmation des PRUs vous sera utile et surtout vous donnera envie de réaliser des applications plus complexes, utilisant le SPI ou l’ADC par exemple, ou encore les timers.

ET Voilà!!!

Les fichiers audio dans LTspice pour la simulation d’effets

Cet article explique comment importer et exporter des fichiers audio (au format wav) dans LTspice.
Cela est très intéressant pour tester un effet analogique et simuler par exemple le rendu d’une pédale de guitare!

Commençons par un montage de base avec un AO:

baseInv

C’est un amplificateur inverseur. Comme R1 = R2, c’est un inverseur simple.

L’AMPLIFICATEUR OPERATIONNEL

Pour l’ampli op, on a choisi un ampli op standard LM741. 

Je passe rapidement sur les détails techniques : on utilise le fichier LM741.sub et on ajoute la directive
« .lib C:\monchemin\LM741.sub »
On renomme opamp2 en LM741/NS.

LM741

Il reste à ajouter une alimentation symétrique en -4.5v, +4.5V pour alimenter l’AO. On utilise pour cela deux « cells » avec les labels V+ et V- :alimA0

Ci-joint le circuit inverseur.

AJOUT D’UN FICHIER AUDIO EN ENTREE

Le « trick », c’est de presser la touche « ctrl » tout en cliquant droit sur le générateur de tension (le composant « voltage »):

EntreeWav1

Dans le champ « value », on utilise le mot clef wavefile
wavefile= »C:\monchemin\monfichier.wav » chan 0
chan 0 indique de prendre le premier canal, en cas de fichier stéréo.
EntreeWav2
Ci-joint le fichier audio (enregistré avec un smartphone de base) : say it aint so extrait . Ce fichier dure environ 15.2 secondes. Dans la « simulation command », on ajuste la durée à 15.3 secondes.

ENREGISTREMENT DU FICHIER AUDIO EN SORTIE

On ajoute pour cela une directive avec le mot clef .wave :
.wave « C:\monchemin\monfichierWavOut.wav » 16 44100 Vout

  • .wave : pour indiquer que la sortie est un audio au format wav,
  • « C:\… » : le nom du fichier de sortie,
  • 16 : nombre de bits de quantification – 16 bits est la valeur standard,
  • 44100 : fréquence d’échantillonnage en Hz, c’est à dire le nombre de valeurs par seconde. 44100, c’est la qualité CD,
  • Enfin, Vout est le label qui correspond à la sortie.
  • SortieWav

SIMULATION D’UN EFFET PASSE-BAS

Pour que cela devienne intéressant, on transforme notre circuit inverseur en un passe-bas par l’ajout d’une capa en parallèle de la résistance R2.

SortieWavPasseBas

La fréquence de coupure du passe-bas est 1/(2*pi*R2*C1). Avec C1=160n, cette fréquence est d’environ 1kHz.

On lance la simulation. Notez bien que la simulation demande une latence considérable. Il est conseillé de tester son circuit sur des fichiers courts.

Ci-joint, le fichier audio en sortie du passe-bas : say it aint so extrait passe base 1kHz .

CONCLUSION

L’audio en entrée et en sortie, la possibilité de simuler des effets analogiques. Rien à dire : LT spice c’est génial!

P.J. : le schéma spice pour le passe-bas avec audio en entrée et sortie : PB

Comment importer une diode Zener dans LTspice?

Bonsoir,

Je reprends mon blog. Je me suis  découvert une passion pour l’électronique pendant l’année 2015 et je ponds ici un premier article technique.

J’utilise un logiciel gratuit (?) LTspice qui permet de modéliser n’importe quel schéma d’électronique ANALOGIQUE. A la root’s quoi.

Je trouve ce logiciel génial. Il permet de faire un pont entre le fer à souder et la simulation sur ordi. La théorie et la pratique quoi. Par contre, il faut pas mal barouder sur le net pour trouver les bonnes informations quand ça coince.

Entrons dans le vil du sujet: l’objectif de ce post est d’expliquer comment importer un modèle de composant dans LTspice, en l’occurrence une diode Zener 5.1V.

Le contexte: je souhaite obtenir une alimentation symétrique (+4.5V,0V,-4.5V) à partir d’une pile 9V.

Voici le schéma du montage sous LTspice :

AlimZenerDebut2

En rouge, entourée la diode Zener. Le modèle ne me convient pas.

Je veux une diode Zener à 5.1V.

Voici comment j’ai procédé:

  1. chercher une librairie sur le net. google  » ltspice zener diode « . On choisit un lien proposé, par exemple: http://www.simonbramble.co.uk/lt_spice/ltspice_lt_spice_models.htm (lien valide au 2/01/2015). On télécharge le fichier »spicemodels_zener_diodes.zip » en cliquant sur le lien « Zener Diodes« .On le dé-zip et on extrait un fichier « zener_diodes.txt ».
  2. Il y a un petit problème : ce fichier contient des erreurs, il manque des « .ENDS » à la fin de certaines sous-fonctions (qui commencent par. SUBCKT). Alors, soit on ajoute des « .ends » partout où il en manque, et il en manque! J’ai opté pour une autre solution: j’ai recopié les définitions (des diodes) qui m’intéressent dans un nouveau fichier « ZenerDiodesBZX84.lib ». Comme son nom l’indique, je n’ai gardé que les diodes zener de type « BZX84 ». J’ai vérifié qu’aucun « .ends » ne manque à l’appel. J’ai ensuite placé ce fichier dans un répertoire de mon choix « G:\Users\Laurent\Documents\LTspice\modelWeb ». Il n’est pas nécessaire de le placer dans un sous-répertoire de LTspice, et je le déconseille.
  3. Je lance dans LTspice. Je crée le beau circuit qui contient une diode Zener. Il n’y a pas de diode zener 5.1V!
    1. J’ajoute la directive SPICE : « .lib G:\Users\Laurent\Documents\LTspice\modelWeb\ZenerDiodesBZX84.lib« , afin que LTspice prenne en compte ma librairie de diodes Zener.
    2. Je vais avec la souris sur le texte associé à la diode. Je clique droit et je remplace le texte « D » par « DI_BZX84C5V1 » pour avoir une diode Zener bzx84C5V1 qui a un seuil de 5.1V.
      AlimZenerRes
      C’est presque fini. Presque!
    3. Là c’est tricky. Dernière étape: il faut indiquer à LTspice que le composant est défini de manière externe, c’est à dire dans ma librairie. Pour cela, il faut placer la souris sur la diode et presser la touche ctrl tout en cliquant droit avec la souris. Il apparaît une fenêtre « Component Attribut Editor ». L’attribut « Prefix » a pour valeur « D » pour indiquer que c’est une diode. On remplace cette valeur par « X », qui indique que c’est un composant défini de manière externe.
      attributEditor
      Attribute Editor avant changement

      attributEditorAfter
      Attribute Editor après changement

J’ai pas mal galéré entre le fichier .lib qui contenait des erreurs et surtout le changement de la valeur de l’attribut « Prefix ».

Ce qui est à retenir:

  1. On peut ajouter des composants dont on trouve la définition sur le net. On les inclut dans un circuit avec la directive Spice: « .lib maLibrairie.lib ».
  2. S’il s’agit d’une variante d’un composant existant déjà dans Spice, on donne au champ « Prefix », dans la fenêtre « Component Attribut Editor », la valeur « X », qui signifie « Externe ».

J’ai trouvé la solution sur le site « Adding Spice Models to LTspice« .

Je mets en lien la librairie et le circuit avec la diode Zener en question.