Windows considère toujours qu’il est le seul OS sur une machine. L’une des fâcheuses conséquences, c’est de penser qu’il y a un problème avec les speakers de son ordi pendant des mois, alors que tout fonctionne bien. Si on mute les speakers sur Windows et qu’on boote en linux ensuite, le setting reste dans le bios et linux ne peut plus le changer. Il faut donc toujours laisser les speakers avec du volume au moment de fermer Windows. Merci la vie.
J’ai recommencé à jouer avec la communication USB du TinyFPGA, à l’aide de ce programme : https://github.com/davidthings/tinyfpga_bx_usbserial
Je n’ai pas tout saisi le fonctionnement du pipeline, mais ce que j’ai pu observer, c’est qu’en maintenant le signal « uart_valid » de la transmission à 1, le caractère placé dans uart_data est transmis à l’infini, le plus rapidement possible. (J’envoie ici 97, ou « a » en ASCII).
Pour n’envoyer qu’une seule fois le caractère, je compte 2 transitions d’horloge où je maintiens uart_valid à 1. Voici la section du code Verilog (code complet à la fin de l’article) :
reg[26:0] count1hz;
always @(posedge clk_48mhz) begin
if (count1hz == 0)
uart_in_valid <= 1'b1;
if (count1hz >= 10000) //valid doit être à 1 pendant n+1 cycles complets de clock pour transférer n byte
uart_in_valid <= 1'b0;
end
always @(posedge clk_48mhz) begin
if (count1hz >= 47999999) //tick 1Hz
count1hz <= 0;
else
count1hz <= count1hz + 1;
end
assign uart_in_data = 97;
Et voici le programme python . J’utilise python 3.11.3 sur Fedora 38 et pyserial 3.5
import serial
ser = serial.Serial("/dev/ttyACM0")
idx = 0
while(True):
msg_lenght = ser.in_waiting
if msg_lenght > 0:
idx = idx + 1
print(idx)
ser.read(msg_lenght)
Première constatation, le buffer est optimisé pour 64 caractères. Si je maintiens uart_valid pendant plus de 64 transitions d’horloge, seulement 64 caractères se rendent jusqu’à python. Pour arriver à 128 (donc 2 paquets USB), il faut attendre entre 5000 et 10000 transitions. En approximant vers le haut, cela signifie une fréquence de ~5kHz (L’horloge va à 48Mhz). Donc le taux de répétition des paquets est de 10kHz, ce qui fait 640ko/s, ou 6,4 Mbaud.
Honnêtement, je m’attendais à pire. Je lui ai quand même donné une chance en lisant d’un seul coup les 64 octets de son buffer, à l’aide de la commande in_waiting, au lieu d’une boucle for et d’un read sur chaque octet individuel (à proscrire).
Comparé au potentiel théorique de l’USB 2.0 de 48Mo/s, on est loin du compte. Toutefois, pour des applications où le débit d’information est bas, pyserial (et python en général) est très simple à utiliser.
Je suis à la recherche d’alternatives pour aller plus vite. Il y a la librairie pyserialtranfer (https://github.com/PowerBroker2/pySerialTransfer), mais je ne suis même pas sûr qu’il y aura un gain de vitesse. Sinon, essayer de voir ce qu’il se fait avec c++. Autre truc intéressant à comprendre, comment être sûr que le protocole à 480Mbit/s est utilisé. Parce que USB1 a la spécification d’aller à 12Mbit/s, ce qui est beaucoup plus dans l’ordre de grandeur que ce que je mesure (6Mbit/s). Donc peut-être que c’est aussi un problème de kernel et d’identification de la part du tinyFPGA. Peut-être (probablement) que l’implémentation de davidthings se base sur le standard USB1. Je ne connais pas les différences fondamentales au niveau du hardware.
EDIT : j’ai vérifié dans le kernel (avec la commande lsusb, puis lsusb -t) et le tinyFPGA est listé comme un device avec 12M de vitesse (USB1) :
Port 3: Dev 102, If 1, Class=CDC Data, Driver=cdc_acm, 12M
Ceci explique cela. La quête vers l’USB2 sera peut-être plus ardue que je le pensais. Cela change un peu ma conclusion : pyserial est une librairie parfaitement adaptée pour l’utilisation avec des devices suivant le protocole USB1.
Le code verilog complet :
/*
Voir le code pour le usb serial ici
https://github.com/davidthings/tinyfpga_bx_usbserial
*/
module uart_top (
input pin_clk,
inout pin_usb_p,
inout pin_usb_n,
output pin_pu,
output pin_led,
);
wire clk_48mhz;
wire clk_locked;
// Use an icepll generated pll
pll pll48( .clock_in(pin_clk), .clock_out(clk_48mhz), .locked( clk_locked ) );
// // LED
// reg [22:0] ledCounter;
// always @(posedge clk_48mhz) begin
// ledCounter <= ledCounter + 1;
// end
// assign pin_led = ledCounter[ 22 ];
// Generate reset signal
reg [5:0] reset_cnt = 0;
wire reset = ~reset_cnt[5];
always @(posedge clk_48mhz)
if ( clk_locked )
reset_cnt <= reset_cnt + reset;
// uart pipeline in
reg [7:0] uart_in_data;
reg uart_in_valid;
reg uart_in_ready;
wire [7:0] uart_out_data;
wire uart_out_valid;
wire uart_out_ready;
// usb uart - this instanciates the entire USB device.
usb_uart uart (
.clk_48mhz (clk_48mhz),
.reset (reset),
// pins
.pin_usb_p( pin_usb_p ),
.pin_usb_n( pin_usb_n ),
// uart pipeline in
.uart_in_data(uart_in_data),
.uart_in_valid(uart_in_valid),
.uart_in_ready(uart_in_ready),
//.uart_out_data(uart_in_data),
//.uart_out_valid(uart_in_valid),
//.uart_out_ready(uart_in_ready)
);
// USB Host Detect Pull Up
assign pin_pu = 1'b1;
reg[26:0] count1khz;
always @(posedge clk_48mhz) begin
if (count1khz == 0)
uart_in_valid <= 1'b1;
if (count1khz >= 10000) //valid doit être à 1 pendant n+1 cycles complets de clock pour transférer n byte
uart_in_valid <= 1'b0;
end
always @(posedge clk_48mhz) begin
if (count1khz >= 47999999) //tick 1Hz
count1khz <= 0;
else
count1khz <= count1khz + 1;
end
assign uart_in_data = 97;
endmodule
Cela fait longtemps que je veux faire de la détection hétérodyne, et j’ai récemment eu l’occasion de m’y mettre avec mon laser He-Ne qui a la particularité d’avoir deux modes axiaux séparés par 1GHz.
Matériel
L’idée, c’est d’utiliser une photodiode assez rapide (temps de montée <1ns) branchée sur un récepteur radio dont la plage de fréquence est suffisamment élevée pour capter le signal. J’ai donc choisi d’utiliser ma radio logicielle rtl-sdr de Noo-Elec qui peut se synthoniser jusqu’à 1,7GHz avec une largeur d’acquisition de 2,4MHz. La photodiode est la FDS02 de thorlabs et un temps de montée de 47 ps et de descente de 246 ps. L’impédance de ma radio est de 50Ohm et la capacitance de jonction de la photodiode non-biaisée est de 2pF, ce qui fait théoriquement que le circuit peut observer des signaux jusqu’à 60GHz avant de perdre 3dB. Je voulais mettre toutes les chances de mon côté, étant donné que le bruit de mon récepteur radio est tout de même élevé. La photodiode coûte 90$US et la radio logicielle, 35$US, le laser He-Ne reste le plus cher dans tout ça, à 260$US sur ebay. On peut accomplir de la science vraiment intéressante à faible budget!
La construction est simple : j’ai soudé les deux broches de la photodiode sur un câble SMA coaxial relié à la radio. La photodiode est placée directement dans le faisceau de sortie du laser. La radio est branchée dans un port USB de l’ordinateur et le programme Gqrx est utilisé pour synthoniser la fréquence hétérodyne et afficher la FFT en temps réel.
Mesure
Voici une capture d’écran vidéo du signal obtenu sur ma radio :
Discussion
La cavité du laser fait 14cm. Cela veut dire que les modes axiaux supportés sont espacés de v = c/2d = 3e8/(2*0,14) = 1,071GHz. Ce calcul rapide m’a permis de rapidement scanner la radio pour trouver la fréquence du phénomène, autour de 1,08GHz. Le signal à 1,08GHz pile est évidemment un contaminant radio provenant de l’environnement, probablement de l’aéroport de Québec dans ce cas-ci puisque c’est dans la bande réservée à l’aviation.
Le fasiceau du laser He-Ne est à 632nm, ce qui fait que la fréquence optique est de 4,7*10^14Hz, ce qui est beaucoup trop rapide pour être capté par n’importe quelle électronique. Avec la détection hétérodyne, ce qu’on mesure, c’est l’enveloppe du battement, qui a une fréquence de | f1 – f2 |, soit la différence entre les fréquences des deux modes. Cela est rendu possible parce que les deux modes tombent exactement au même endroit sur la photodiode, qui répond à l’intensité lumineuse du signal total.
Au départ, je m’attendais à mesurer un signal plutôt stable, qui s’allume et s’éteint selon le nombre de modes dans la cavité. En effet, puisque le laser se réchauffe au départ, le verre du tube se dilate petit à petit, ce qui joue sur la longueur de la cavité, et donc sur la fréquence des modes supportés. La courbe de gain reste peu impactée par ce phénomène (je crois), cela signifie que les modes se promènent à l’intérieur de cette courbe, et qu’on a tantôt un, tantôt deux modes présents, avec une fréquence qui reste à ±1,5GHz (la largeur de la courbe de gain dans le laser He-Ne due au « doppler broadening »). Ou, à la rigueur, si le verre du tube se dilatait de l’ordre de 100 microns ou plus dû au réchauffement, on observerait une diminution progressive de la fréquence de battement d’environ 1MHz.
Or, un autre effet est observé, soit une variation rapide et dans les deux sens (un va-et-vient, à deux fréquences différentes) de la fréquence hétérodyne, avec un amplitude d’environ 400kHz. Ce sont les espèces de paraboles couchées que l’on observe dans la FFT au début de la vidéo. La vitesse de ce phénomène ralentit au fur et à mesure que le laser se réchauffre, jusqu’à atteindre un point de relative stabilité. Cela prend environ 30min de réchauffement pour atteindre ce moment, ce qui correspond bien avec mes autres mesures de stabilité en polarisation. À la fin du vidéo (minute 2, qui correspond dans la réalité à la minute ~30), on voit comment le laser devient stable, mais sensible à toute fluctuation de température, puisqu’il est exposé à l’air libre sans contrôle sur le transfert thermique. On atteint tout de même déjà une stabilité sur la fréquence à moins de 100kHz.
La question est donc : qu’est-ce qu’on observe? Pourquoi? Après plusieurs heures de recherches dans mes manuels, dont nottament le « Lasers » de Siegman et le Saleh et Teich, Fundamentals of photonics part II, j’ai compris que le phénomène s’appelle « frequency pulling ». Voici les deux pages traitant de ce sujet dans le Saleh et Teich :
En bref, ce que j’en comprends c’est que l’interaction des photons avec le milieu de gain crée un léger déphasage qui dépend de la position sur la courbe de gain (donc de la fréquence). Cette non-linéarité est tracée à la figure 16.1-3. Le déphasage se traduit en un changement de la fréquence du mode supporté, puisqu’un aller-retour dans la cavité doit donner exactement un multiple de 2pi en phase pour que l’onde soit stationnaire. Plus on s’éloigne du centre de la courbe de gain, plus le déphasage augemente, donc plus la fréquence des modes est « tirée » vers le centre.
Lorsque le laser se réchauffe, les deux modes se promènent le long de cette courbe de non-linéarité, ce qui fait que la différence entre leurs fréquences augmente, puis diminue. Par exemple, supposons qu’un mode est plus proche du centre et que l’autre apparaît tout juste. L’effet du frequency pulling sera maximal, donc la fréquence hétérodyne sera la plus basse. Ensuite, lorsque les deux modes sont à égale distance par rapport au centre de la courbe de gain, la fréquence hétérodyne atteint un maximum, puis redescend à sa valeur initiale de manière symétrique. Cela explique bien la forme de parabole observée dans la FFT du signal.
La seule chose que je ne m’explique pas, c’est le saut périodique d’environ 500kHz lorsque les modes apparaissent et disparaissent. (Le phénomène de parabole est observé tantôt à 1079,5MHz, tantôt à 1080MHz. Il faut bien garder quelques mystères!
À la page 469 du Siegman, un calcul de frequency pulling est fait pour le cas d’un laser He-Ne avec 10% de gain en puissance par aller retour. Cela donne un ratio de 1,6*10^-3. Dans mon cas, j’ai seulement deux modes et j’observe un ratio de ~400kHz / 1GHz = 4*10^-4. Il y a seulement un facteur 4 de différence, ce qui s’explique sûrement par les différences entre les paramètres de mon laser et ceux de l’exemple. Cela me permet toutefois d’évaluer le gain en puissance par aller-retour à (4*10^-4)*2*pi*2 = 0,5%. C’est surprenamment peu, mais le laser est tout de même très court. Étant donné que je ne me suis pas penché sur les détails du calcul et ses approximations, je ne suis pas très confiant sur ce dernier chiffre, c’était davantage pour montrer qu’on peut se servir de la mesure pour calculer d’autres paramètres du laser.
Dans une prochaine expérience, il serait intéressant d’utiliser la détection hétérodyne avec une diode laser, pour voir quels autres phénomènes seraient observables.
Il est de ces questions qui nous empêchent de dormir la nuit. Je me suis repensé sur mon projet de Fabry-Perot et de laser He-Ne stabilisé, avec l’intension de peut-être utiliser une photodiode en détection hétérodyne.
Jusqu’à présent, je pensais que le laser He-Ne avait un seul mode axial dans la cavité, mais qu’il se découlait en deux polarisations. Ainsi, les deux polarisations avaient exactement la même fréquence (avec une très petite largeur de raie). C’était naïvement en prenant comme prémice que c’est ce qu’il se passe dans une cavité, un guide d’onde, etc. Il faut tout le temps faire x2 le nombre de modes pour tenir compte des deux polarisations.
Je ne sais plus exactement d’où m’est venue l’idée d’investiguer davantage le sujet. Je crois que je cherchais une façon d’avoir deux fréquences avec un He-Ne. En allant sur le site de Thorlabs, je suis tombé sur le diagramme suivant : (source : https://www.thorlabs.com/newgrouppage9.cfm?objectgroup_id=10776 )
Mon fournisseur de laser (siliconsam) a beaucoup de choses à dire sur le sujet, c’est difficile de faire le tri dans toute cette information : https://www.repairfaq.org/sam/laserhen.htm
En bref, la transition qui nous intéresse dans le Néon, qui produit la raie à 632,8nm, a une largeur d’environ 1,5GHz (le chiffre exact varie selon les sources et probablement les calculs). Cela est dû au fait que les atomes dans le gaz à température ambiante, ont une distribution gaussienne de vitesse par rapport à l’axe du laser. Par effet Dopler, cela crée une distribution similaire dans la courbe de gain selon la fréquence pour l’émission stimulée. En choisissant la longueur de la cavité, on peut ainsi construire un laser qui a exactement deux modes longitudinaux.
Avec v=nc/2L, on trouve L = nc/2v. Cela fait L = 2*3e8m/s/2*1,5e9Hz = 0,2m. Avec un laser de 20cm de long (c’est ce que j’ai), seulement deux modes de la cavité peuvent tomber dans la largeur de la courbe de gain. Ok cool. Mais maintenant, pourquoi ces deux modes ont-ils une seule polarisation, et qui plus est, toujours orthogonale à l’autre?
En fait, au gré des changements de température, la longueur de la cavité change légèrement, ce qui fait que les modes se « promènent » dans la courbe de gain. Si rien n’est stabilisé, la polarisation se promène cycliquement entre les deux extrêmes, puisque les modes ont des positions (et donc des intensités) variables dans la courbe de gain. Cette propriété est utilisée dans la méthode de stabilisation de mon laser. Puisque les deux modes se séparent parfaitement par leur polarisation, on peut s’arranger pour contrôler la longueur de la cavité au moyen de la température du tube, afin que les deux modes gardent leur position à l’intérieur de la courbe de gain, et donc leur fréquence.
En lisant davantage, je suis tombé sur le concept de « spectral hole burning in a Doppler-broadened medium » (p.674 du Saleh et Teich). En bref, à cause de la symétrie de la cavité (aller-retour du faisceau), les atomes qui ont la vitesse +v et -v sont saturés. Pourtant, cela ne peut pas être la source du phénomène, puisque les modes se promènent au-delà de cet effet miroir, et les polarisations restent définies et orthogonales.
Se pourrait-il qu’il y a ait le même genre de hole burning dans la courbe de gain, mais pour la polarisation? Difficile à trouver dans les internets. Google me ramène encore à la page de siliconsam, je trouve un extrait pertinent :
It is well known that adjacent longitudinal modes in red (632.8 nm) HeNe lasers (at least) tend to be orthogonally polarized as discussed above. This is a weak coupling as a magnetic field, Brewster plate, or even some asymmetry in the cavity can affect it or kill it entirely. And some lasers will cause the polarization to suddenly flip as modes cycle through the gain curve. However, the majority of modern well designed red HeNe lasers will exhibit this phenomenon.
This is not necessarily true of « other color » HeNes. My informal tests suggest that in general it is *not*. Long green (543.5 nm), short and long yellow (594.1 nm), and medium length orange (611.9 nm) random polarized HeNe laser heads all exhibited varying degrees of erratic behavior with respect to polarization. Usually, modes when part of the way through the gain curve and then either flipped abruptly or oscillated between polarizations for a short time and then flipped. The long yellow head liked to have pairs of adjacent modes with the same polarization but exhibited the flipper behavior as well. However, adding a modest strength magnet near the long green seemed to force it to behave with adjacent modes having orthogonal polarization. I have no idea if this is significant or the long green HeNe was simply a cooperating sample.
But what is the underlying cause?
(From: A. E. Siegman (siegman@stanford.edu).)
The reason that HeNe lasers can run – more accurately, like to run – in multiple axial modes is associated with inhomogeneous line broadening (See section 3.7, pp. 157-175 of my book) and « hole burning » effects (Section 12.2, pp. 462-465 and in more detail in Chapter 30) in the Doppler-broadened laser transitions commonly found in gas lasers (though not so strongly in CO2) and not in solid-state lasers.
The tendency for alternate modes to run in crossed polarizations is a bit more complex and has to do with the fact that most simple gas laser transitions actually have multiple upper and lower levels which are slightly split by small Zeeman splitting effects. Each transition is thus a superposition of several slightly shifted transitions between upper and lower Zeeman levels, with these individual transitions having different polarization selection rules (Section 3.3, pp. 135-142, including a very simple example in Fig. 3.7). All the modes basically share or compete for gain from all the transitions.
The analytical description of laser action then becomes a bit complex – each axial mode is trying to extract the most gain from all the subtransitions, while doing its best to suppress all the other modes – but the bottom line is that each mode usually comes out best, or suffers the least competition with adjacent modes, if adjacent modes are orthogonally polarized.
There were a lot of complex papers on these phenomena in the early days of gas lasers; the laser systems studied were commonly referred to as « Zeeman lasers ». I have a note that says a paper by D. Lenstra in Phys. Reports, 1980, pp. 289-373 provides a lengthy and detailed report on Zeeman lasers. I didn’t attempt to cover this in my book because it gets too complex and lengthy and a bit too esoteric for available space and reader interest. The early (and good) book by Sargent, Scully and Lamb has a chapter on the subject. You’re probably aware that Hewlett Packard developed an in-house HeNe laser short enough that it oscillated in just two such orthogonally polarized modes, and used (probably still uses) the two frequencies as the base frequencies for their precision metrology interferometer system for machine tools, aligning airliner and ship frames, and stuff like that.
C’est quand même nice qu’il ait écrit directement à Siegman (Le livre est bien sûr Lasers, et je l’ai dans ma bibliothèque! Merci le cours de laser de l’université!)
Il se passe donc un effet particulier avec cette transition précise, dans les orbitales de l’atome de Néon. L’effet Zeeman, même sans champ manétique externe est présent et influence la polarisation. Ainsi, les deux modes compétionnent quand même pour les mêmes atomes, et la manière de les rendre le moins couplés possible est d’avoir des polarisations complètement orthogonales, de manière à optimiser le gain sur les deux modes en même temps.
De nombreux doctorats se sont écrits sur le sujet, et j’ai pas la prétention d’avoir tout compris, mais après ces recherches de plusieurs heures, je crois avoir trouvé une certaine paix d’esprit face à ce questionnement.
Objectif : partir d’un saxophone fonctionnel et rajouter un genre de MIDI real-time, pour pouvoir en jouer en silence et le brancher sur des synthétiseurs.
Pour la première itération de preuve de concept, j’ai voulu explorer l’utilisation d’un capteur de pression (BMP085, c’est celui que j’avais sous la main) placé sur le trou de la clé d’octave. Je trouvais que c’était la méthode la moins invasive, avant de jouer dans le bec. Voici de quoi avait l’air le montage :
J’ai utilisé la librairie adafruit BMP085 ainsi que le traceur série d’arduino pour aficher les données, à la fréquence maximale.
#include <Adafruit_BMP085.h>
/***************************************************
This is an example for the BMP085 Barometric Pressure & Temp Sensor
Designed specifically to work with the Adafruit BMP085 Breakout
----> https://www.adafruit.com/products/391
These pressure and temperature sensors use I2C to communicate, 2 pins
are required to interface
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
BSD license, all text above must be included in any redistribution
****************************************************/
// Connect VCC of the BMP085 sensor to 3.3V (NOT 5.0V!)
// Connect GND to Ground
// Connect SCL to i2c clock - on '168/'328 Arduino Uno/Duemilanove/etc thats Analog 5
// Connect SDA to i2c data - on '168/'328 Arduino Uno/Duemilanove/etc thats Analog 4
// EOC is not used, it signifies an end of conversion
// XCLR is a reset pin, also not used here
Adafruit_BMP085 bmp;
void setup() {
Serial.begin(9600);
if (!bmp.begin()) {
Serial.println("Could not find a valid BMP085 sensor, check wiring!");
while (1) {}
}
}
void loop() {
//Serial.print("Temperature = ");
//Serial.print(bmp.readTemperature());
//Serial.println(" *C");
//Serial.print("Pressure = ");
Serial.println(bmp.readPressure());
//Serial.println(" Pa");
// Calculate altitude assuming 'standard' barometric
// pressure of 1013.25 millibar = 101325 Pascal
//Serial.print("Altitude = ");
//Serial.print(bmp.readAltitude());
//Serial.println(" meters");
//Serial.print("Pressure at sealevel (calculated) = ");
//Serial.print(bmp.readSealevelPressure());
//Serial.println(" Pa");
// you can get a more precise measurement of altitude
// if you know the current sea level pressure which will
// vary with weather and such. If it is 1015 millibars
// that is equal to 101500 Pascals.
//Serial.print("Real altitude = ");
//Serial.print(bmp.readAltitude(101500));
//Serial.println(" meters");
//Serial.println();
//delay(500);
}
Le bruit est d’environ 2-3 Pa et le signal autour de 5-10 Pa, lorsque je souffle assez fort, mais sans faire vibrer l’anche du bec. On peut donc détecter le souffle de cette manière, mais ça manque de fiabilité. Je pensais que le changement de pression serait plus important, mais il semble que la vitesse du flux d’air est beaucoup plus significative.
À essayer :
Les nouveaux capteurs de pression ont un bruit beaucoup plus faible (~0,02 Pa selon les datasheet). À acheter parce que je n’en ai pas.
Mettre un micro MEMS pour comparer la sensibilité au signal
Parce que je suis toujours en train de reperdre des heures à chaque fois que je réinstalle Quartus sur un nouvel ordi. Voici la solution magique qu’il faut faire après installation.
La plupart des interfaces haptiques se basent sur un dispositif électromécanique (moteur miniature et masse décentrée) afin de produire une vibration.Bien que le niveau d’intensité puisse être contrôlé, la plage dynamique dans les sensations très faibles reste difficile à atteindre. De plus, la vibration produit également un son, ce qui peut interférer avec une interface auditive, ou déconcentrer l’usager.
Dans cette exploration technologique, je me demande quels sont les possibilités qu’offrent les nouveaux mini modules thermoélectriques disponibles comercialement. Je me suis concentré sur deux pièces fabriquées par CUI, le CP2088-219 et le CP0734-238. Le premier fait 8x8mm de large, et le second, 3,4×3,4mm (!). La raison derrière mon choix est la précision spatiale, la faible consommation électrique et la facilité d’intégration dans un assemblage complètement portatif.
L’une de mes idées plus générales était de se servir de ce bracelet comme d’un facilitateur empathique à la limite du conscient, en reproduisant en temps réel une mesure physiologique provenant d’une autre personne. J’en parlerai plus en détail dans la conclusion. Comme d’habitude, toutes les bonnes idées manquent d’originalité et ont déjà été brevetées (https://patents.google.com/patent/WO2013058886A1), mais c’est pas ce qui va m’empêcher de faire des recherches dans ce domaine.
Heatsink
Afin d’optimiser le transfert thermique (Q et dQ/dt), un heatsink doit être attaché sur la face chaude du peltier. Comme je ne savais pas trop ce que je faisais, j’ai choisi d’y aller avec la simplicité : un heatsink en alu avec des ailettes super larges et espacées, pour favioriser un refroidissement passif. J’ai aussi exploré un micro blower fan, mais je ne lui ai pas trouvé de heatsink compatible. Bref, il y a une grande différence entre faire un cours de transfert thermique théorique, et être confronté à la jungle des pièces disparates en pratique. Je comprends les concepteurs de fonctionner avec des assemblages déjà faits, ou bien de concevoir des pièces sur mesure. En outre, je n’ai pas trouvé de distributeur qui rend cela clair. Bref, après en avoir acheté plusieurs un peu au hasard, je me suis arrêté sur celui-ci : ATS-52150G-C1-R0. Il fait 15x15mm de large et a une résistance thermique de 11,7 degC/W. Étant donné que mon utilisation est avec un rapport cyclique très faible (le peltier est pulsé et beaucoup plus souvent à off qu’à on), j’ai estimé que cela serait bon.
Estimation du seuil de sensibilité et du seuil de douleur
En utilisant une source de courant ajustable entre 0 et 2A, et entre 0 et 4V et le peltier CP2088 en contact direct avec l’index du côté froid, et le heatsink susmentionné du côté chaud, j’ai pu produire des transferts thermiques entre 0 et 4W, pour des durées de 1 à 9 secondes avec le montage électronique que je présenterai plus tard. Le seuil de sensibilité (mesure très subjective) est un peu en-dessous de 0,5W. Le seuil de douleur était autour de 3W. Enocre une fois, c’est subjectif. La sensation de douleur ne provient pas d’une brûlure réelle (surtout que le peltier refroidit), mais du gradient super élevé de changement de température, qui affole les capteurs physiologiques. Passer par exemple de 25 degrés à 20 degrés en une fraction de seconde semble simuler le contact subit avec un objet extrêmement froid, d’où la sensation de douleur et le réflexe de vouloir retirer son doigt. Je ne connais pas bien les mécanismes de reset biologiques, mais la sensation perdure plusieurs secondes, voire minutes, après que la puissance électrique soit retirée du peltier, un peu à la manière de la persistence rétienne, où un flash de lumière reste dans le champ visuel.
Ce que j’ai remarqué, c’est que les capteurs de température du corps sont beaucoup plus sensibles au changement de température qu’à la valeur absolue. Une température de 20 ou de 15 degrés ne produit que peu de sensation, et avec le peu de puissance de mon peltier, je ne peux descendre beaucoup plus bas, considérant la puissance thermique que fournit le corps et l’efficacité de mon heatsink. De plus, puisque mon système est portatif et à batterie, la consommation électrique doit être considérée. Utiliser le peltier dans un régime pulsé, bien qu’étant déconseillé la plupart du temps, est ici une avenue intéressante pour augmenter le ratio sensation / consommation électrique, métrique réelle d’efficacité de mon système.
J’ai aussi fait un test rapide avec le CP0734 pour voir s’il était possible de miniaturiser davantage. Hélas, son Qmax est limité à 0,2W. Cela est compensé par sa taille plus petite, mais tout de même. Je pense qu’il y a aussi une limite de surface pour les capteurs de température dans la peau, à investiguer. Bref, je l’opérais toujours au maximum de puissance sans rien sentir. Le seul endroit où la sensation était vive était sur le côté du petit doigt, à l’approche de la paume. Ce côté de la main, la tranche extérieure, est la région la plus sensible que j’aie pu trouver, du bout des doigts au coude. On pourrait penser à intégrer un tel peltier dans une bague, mais cela demanderait une miniaturisation poussée du reste de l’électronique.
Électronique de contrôle
Bien que mon intuition initiale était de simplement brancher le peltier sur un PWM, cela allait à l’encontre de tout ce qui se fait. J’ai lu des forums entiers expliquant pourquoi c’était une idée stupide de faire cela (réponse courte : la dissipation thermique va en RI^2 tandis que le transfert entre les deux faces est linéairement proportionnelle au courant. Et la chaleur produite par le peltier lui-même se rajoute au système.) Tout cela est bien beau dans les faits, mais la réalité de mon design est que j’uilise une batterie lithium et un microconrtôleur à niveau logique de 3,3V, et que je dois allumer et éteindre un courant de près de 2A. L’électronique pouvant accomplir tout cela existe, mais elle a de sérieuses limitations.
En outre, j’ai cherché un petit moment un mosfet pouvant être activé par aussi peu que 3,3V (Vgs) et fournir une résistance Rds dans les milliohms, afin de permettre un courant de 2A dans le peltier qui fait 1,43 ohm avec seulement 3,7V en entrée. Mon choix s’est porté sur le SUP40012EL-GE3.
J’aurais pu utiliser un convertisseur DC-DC pour augmenter le voltage et utiliser un mosfet ordinaire. Mais cela complexifiait déjà le circuit, pour peu d’avantages. J’ai décidé de me concentrer à avoir un premier prototype fonctionnel, et voir par la suite comment je pourrais optimiser la consommation électrique.
Dans mon exploration, j’ai voulu faire justement un convertisseur DC-DC pour pouvoir ajuster le voltage à l’entrée du peltier entre 0 et 3,7V (dans le but de contrôler le courant et donc le transfert thermique). Je me suis rendu compte (j’aurais dû lire Art of electronics pour le savoir) que les mosfets demandent un courant important pour être allumés à haute fréquence (à cause de leur capacitance élevée de gate). Et que généralement, les mosfets optimisés pour avoir une résistance basse à l’état allumé ont également le compromis d’avoir une capacitance élevée. Dans le design d’un convertisseur DC-DC, plus la fréquence est basse, plus l’inductance doit être grosse, ce qui rendait le circuit beaucoup trop massif en pratique. J’ai donc abandonné cette idée.
Mon autre idée était d’utiliser une supercapacitance de 1F pour filtrer la montée de courant et ainsi limiter l’impact sur le peltier. C’était oublier que le mosfet a un diode intégréeà l’intérieur, ce qui transforme le circuit en un charge pump qui double le voltage d’entrée. Étant donné que le peltier a une limite à 3,8V, je devais faire attention avec ma source, et cela rendait l’usage de ma batterie impossible.
Clairement, j’était encore dans une situation d’overdesign, dans le genre de keep it simple. Parfois, trop de doutes et de soucis ralentissent le développement. Je suis donc revenu à mon idée de départ, d’avoir un simple Mosfet avec un PWM à basse fréquence. Au moins, tous ces détours m’on permis de bien comprendre les limites du design et de bien choisir les composants et les paramètres. La gate du mosfet est branchée sur une pin du microcontrôleur à travers une résistance de 100 ohms, et le peltier est branché entre la batterie et le drain du mosfet. La source est reliée au ground.
Le microcontrôleur utilisé est un Feather nrf52840 Express d’Adafruit. J’utilise également une carte de prototypage faite pour les Feather (un proto shield). Le nrf52840 se programme directement avec l’IDE d’Arduino avec toutes les libraires d’Adafruit (une mine d’or). Cela a fait que le bluetooth marchait out of the box, une première dans ma vie (j’ai trop perdu de temps avec des cartes de développement obscures de Nordik, il fallait juste que j’attende qu’Adafruit fasse la grosse job de bras comme il faut).
Programmes
Le programme arduino est le suivant :
/*********************************************************************
This is an example for our nRF52 based Bluefruit LE modules
Pick one up today in the adafruit shop!
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
MIT license, check LICENSE for more information
All text above, and the splash screen below must be included in
any redistribution
*********************************************************************/
#include <bluefruit.h>
#include <Adafruit_LittleFS.h>
#include <InternalFileSystem.h>
// BLE Service
BLEDfu bledfu; // OTA DFU service
BLEDis bledis; // device information
BLEUart bleuart; // uart over ble
BLEBas blebas; // battery
const byte numChars = 16;
char receivedChars[numChars]; // an array to store the received data
boolean newData = false;
int peltierpin = 6;
void setup()
{
pinMode(peltierpin, OUTPUT);
digitalWrite(peltierpin, LOW);
analogWriteResolution(15); //Met la fréquence du PWM à 514kHz, avec 5 bits de résolution (0-31)
//analogWrite(peltierpin, 16384);
Serial.begin(115200);
#if CFG_DEBUG
// Blocking wait for connection when debug mode is enabled via IDE
while ( !Serial ) yield();
#endif
Serial.println("Bluefruit52 BLEUART Example");
Serial.println("---------------------------\n");
// Setup the BLE LED to be enabled on CONNECT
// Note: This is actually the default behavior, but provided
// here in case you want to control this LED manually via PIN 19
Bluefruit.autoConnLed(true);
// Config the peripheral connection with maximum bandwidth
// more SRAM required by SoftDevice
// Note: All config***() function must be called before begin()
Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);
Bluefruit.begin();
Bluefruit.setTxPower(4); // Check bluefruit.h for supported values
//Bluefruit.setName(getMcuUniqueID()); // useful testing with multiple central connections
Bluefruit.Periph.setConnectCallback(connect_callback);
Bluefruit.Periph.setDisconnectCallback(disconnect_callback);
// To be consistent OTA DFU should be added first if it exists
bledfu.begin();
// Configure and Start Device Information Service
bledis.setManufacturer("Adafruit Industries");
bledis.setModel("Bluefruit Feather52");
bledis.begin();
// Configure and Start BLE Uart Service
bleuart.begin();
// Start BLE Battery Service
blebas.begin();
blebas.write(100);
// Set up and start advertising
startAdv();
Serial.println("Please use Adafruit's Bluefruit LE app to connect in UART mode");
Serial.println("Once connected, enter character(s) that you wish to send");
}
void startAdv(void)
{
// Advertising packet
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
Bluefruit.Advertising.addTxPower();
// Include bleuart 128-bit uuid
Bluefruit.Advertising.addService(bleuart);
// Secondary Scan Response packet (optional)
// Since there is no room for 'Name' in Advertising packet
Bluefruit.ScanResponse.addName();
/* Start Advertising
* - Enable auto advertising if disconnected
* - Interval: fast mode = 20 ms, slow mode = 152.5 ms
* - Timeout for fast mode is 30 seconds
* - Start(timeout) with timeout = 0 will advertise forever (until connected)
*
* For recommended advertising interval
* https://developer.apple.com/library/content/qa/qa1931/_index.html
*/
Bluefruit.Advertising.restartOnDisconnect(true);
Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
}
void loop()
{
pollbleuart();
updatePeltier();
}
void pollbleuart() {
static byte ndx = 0;
char endMarker = '\n';
char rc;
while (bleuart.available() > 0 && newData == false) {
rc = bleuart.read();
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
ndx = 0;
newData = true;
}
}
}
void updatePeltier() {
if (newData == true) {
uint16_t intensity = uint16_t(receivedChars[0]-48); //Temps où le Peltier est allumé en millisecondes
if ((intensity < 1) || (intensity > 8)) intensity = 0; //protection de calculs bizarres
analogWrite(peltierpin, 4095 * intensity);
delay(2000); //Le pulse dure 2 secondes
analogWrite(peltierpin, 0);
newData = false;
}
}
// callback invoked when central connects
void connect_callback(uint16_t conn_handle)
{
// Get the reference to current connection
BLEConnection* connection = Bluefruit.Connection(conn_handle);
char central_name[32] = { 0 };
connection->getPeerName(central_name, sizeof(central_name));
Serial.print("Connected to ");
Serial.println(central_name);
}
/**
* Callback invoked when a connection is dropped
* @param conn_handle connection where this event happens
* @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
*/
void disconnect_callback(uint16_t conn_handle, uint8_t reason)
{
(void) conn_handle;
(void) reason;
Serial.println();
Serial.print("Disconnected, reason = 0x"); Serial.println(reason, HEX);
}
En bref, après avoir connecté avec le PC ou tout autre contrôleur, il attend une string composée d’un chiffre de 1 à 8, qui correspond à l’intensité du PWM. La durée du pulse de froid est prédéfinie à 2 secondes. La fréquence du PWM est fixée à 125Hz en prenant la résolution la plus élevée disponible (15 bits) et en la divisant par 4096 pour obtenir seulement 3 bits. (La fréquence de la clock du PWM est de 16Mhz). Dans mes expériences, la résolution sur la sensibilité au gradient de température n’est pas beaucoup plus grande que des entiers entre 0 à 10, d’où le 8 bits. Une fréquence aussi basse permet au Mosfet de suivre facilement avec un courant à sa gate limité à 1mA.
Le code python est tout aussi facile d’utilisation grâce à l’excellent travail d’Adafruit :
from adafruit_ble import BLERadio
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
from adafruit_ble.services.nordic import UARTService
ble = BLERadio()
uart_connection = None
while True:
if not uart_connection:
print("Trying to connect...")
for adv in ble.start_scan(ProvideServicesAdvertisement):
if UARTService in adv.services:
uart_connection = ble.connect(adv)
print("Connected")
break
ble.stop_scan()
if uart_connection and uart_connection.connected:
uart_service = uart_connection[UARTService]
while uart_connection.connected:
s = input("Delay in s : ")
uart_service.write(s.encode("utf-8"))
uart_service.write(b'\n')
J’attends la connexion, puis j’ai mis un input qui envoie la string au microcontrôleur. Dans le code, c’est encore écrit délai, parce qu’au départ, c’était le temps en secondes que j’envoyais dans mes premiers tests.
Plage d’opération
Comme je l’ai dit, il y a 8 intensités de PWM. Il y a plusieurs non linéarités dans l’histoire, mais grosso-modo, il s’agit des plages de 0 à 4W de transfert thermique, avec une résolution de 0,5W (seuil de sensibilité déterminé subjectivement). La non linéarité vient du peltier et aussi peut-être des capteurs de température dans la peau. Toujours est-il que la différence entre 1 et 2 est beaucoup plus marquée qu’entre 7 et 8, cela pourrait être ajusté ultérieurement.
Pour ce qui est de la durée de 2 secondes, elle aussi a été établie empiriquement. La constante de temps du système thermique a été évaluée à environ 2-3 secondes (elle dépend un peu du courant entrée). Cela veut dire que pour une impulsion initale avec une pente infinie, la température (c’était la variable que je mesurais) prenait entre 2 et 3 secondes à atteindre sa valeur. Utiliser une durée de temps plus petite ne produit donc pas une distinction entre les pulses (c’était ce que je voulais évaluer au départ). Et utiliser une durée plus grande ne produit pas vraiment plus de sensation, puisque les transferts thermiques se stabilisent et que la peau s’habitue au contact d’un objet plus froid. Pour cette construction précise, j’ai donc optimisé la durée du pulse à 2s. En utilisant un rapport cyclique de 50%, cela veut dire que la période maximale de l’information qui peut être transmise est de 4s, ou 15bpm. Cela est très lent et empêche son utilisation pour transmettre le rythme cardiaque comme je le souhaitais au départ. Pour la respiration, c’est aussi très limite.
CAD et bracelet
Le code openSCAD pour le bracelet est le suivant :
La fente principale sert à mettre le peltier en contact direct avec la peau. Les deux fentes sur le côté servent à attacher le bracelet avec une bande de tissu cousue avec du velcro.
Perspectives futures
La miniaturisation va être difficile. C’est déjà un exploit d’avoir trouvé des pièces disponibles commercialement pour assembler ce premier prototype. Puisque le dispositif est à faible régime cyclique, l’utilisation d’un supercondensateur d’une couple de farads pourrait être envisagé, afin de réduire la masse de la batterie. Un heatsink plus compact et l’utilisation d’un micro-ventilateur pourrait aussi aider à réduire le volume. Mais la réalité est que pour avoir un effet convainquant, on doit se situer dans le régime thermique de l’ordre de 1W. Cela demande un peltier d’une taille conséquente (environ 1cm^2) ainsi qu’une alimentation pouvant fournir suffisamment de courant (~1A). De plus, l’utilisation du blutooth pour être complètement sans fil est un requis dans une applcation portative, ce qui demande un certain espace supplémentaire.
Vient ensuite le cas d’utilisation. Offrirait-il un avantage dans le cas d’une manette de jeu vidéo par rapport aux dispositifs haptiques déjà existants? L’intégration de « pixels » de froid est-elle une avenue? (Google donne quelques projets de recherche intéressants, qui sont tous plutôt loin de la commercialisation).
Pour ce qui est du transfert d’émotions par le toucher, puisque la constante de temps est assez longue, ce serait limité à des événements très ponctuels. On pourrait penser le corréler avec une métrique plus aboutie que le rythme cardiaque ou la respiration. Par exemple, le niveau d’arousal ou de plaisir, etc. Les limites à cet effet sont plutôt du côté des capteurs et des algorithmes de mesure. Ce qui est intéressant avec une haptique basée sur la température, c’est qu’il serait plus facile d’intégrer un stimuli proche de la limite du conscient, c’est-à-dire qu’on s’en rendrait compte seulement en y portant attention. Cela pourrait offrir un intermédiaire intéressant dans le cas où un système numérique comme un ordi ou un cellulaire cherche à attirer l’attention de manière non-urgente et douce. À voir si le besoin existe et s’il s’agit d’une piste intéressante.
Avec le laser stabilisé en température et le polarimètre version 1, j’ai pu mesurer les états de polarisation suivants :
Mélange de deux polarisations (non polarisé)
Explication : la lame quart d’onde a soit aucun impact (zéro degré par rapport à la polarisaion), soit transforme une partie en polarisation circulaire. Puisque les deux polarisations orthogonales ont une intensité égale, la moitié passe le polariseur devant la photodiode et le signal reste constant.
Polarisation horizontale
Explication : La lame quart soit n’a aucun impact (signal maximal, toute la polarisation passe le polariseur devant la photodiode), soit retire la moitié du signal lorsqu’elle est à 45 degrés (la polarisation est complètement transformée en circulaire, et le polariseur filtre la moitié du signal).
Polarisation verticale
Explication : La lame quart d’onde soit n’a aucun impact, à zéro degré (le polariseur bloque complètement la polarisation à 90 degrés, signal à 0), soit elle convertit complètement le signal en polarisation circulaire lorsqu’elle est à 45 degrés (le polariseur en filtre la moiité et le signal est à 1/2 de la valeur d’intensité).
Transition entre les deux polarisation orthogonales
Polarisation circulaire
Explication : La polarisastion circulaire est convertie en polarisation linéaire par la lame quart d’onde, qui tourne ensuite l’axe de polarisaion linéaire. Cela prend donc une rotation de 90 degrés pour passer d’un maximum à un minimum, parce qu’elle passe à travers un autre polariseur linéaire. La période est deux fois plus grande parce que la lame quart d’onde doit tourner deux fois plus (90 degrés vs 45 degrés).
Mélange entre polarisation linéaire et circulaire
Développements futurs
Le moteur utilisé est simplement un moteur DC sans encodeur et sans régulation de vitesse, ce qui crée des variations, et l’orientation absolue n’est pas accessible. Pour différencier entre la polarisation linéaire et la polarisation circulaire, on remarque que l’information en fréquence est importante. En faisant la transformée de Fourier, on pourrait retrouver le poids des composantes circulaires et linéaires.
Si on s’attend à n’avoir que de la polarisation linéaire, le système proposé par siliconsam dans son laser régulé en température fonctionne mieux, car on peut échantillonner simultanément les deux états, à l’aide d’un cube beamsplitter polarisant et de deux photodiodes, le tout sans pièces mécaniques et sans traitement de signal, ce qui rend le tout très simple.
La position angulaire absolue de la lame quart d’onde permettrait de différencier entre les deux polarisation circulaires (gauche et droite) qui sont décalés en phase de 90 degrés. En ce moment, en regardant seulement le signal sinusoidale sans tenir en compte de l’angle, c’est impossible de voir la différence, parce que le signal passe de zéro au maximum d’intensité dans les deux cas.
L’information en phase et en fréquence est donc aussi importante que l’intensité dans le temps. Le premier débroussaillage est fait, pour la suite, une meilleure optomécanique est nécessaire.
En 2016, pour compléter mon projet d’interféromètre de Michelson, j’avais acheté un laser HeNe en kit, sur ebay. Le tube était tout nu, le power supply était fourni, et le tout venait avec des pièces d’électronique pour stabiliser les modes de polarisation du laser. Puisque la polarisation avait peu d’impact dans mon interféromètre, j’ai simplement utilisé le tube tel quel, en obtenant des bons résulats (ma vidéo ici : https://youtu.be/Cea9mbSiblM )
Récemment, dans mon expérience avec mon polarimètre, j’ai observé une oscillation entre deux polarisations linéaires orthogonales. Le tout se comporte comme si le système est une somme de deux ondes avec une polarisation en x et y (selon une orientation spatiale arbitraire autour de l’axe du faisceau) qui oscillent. En lisant un peu, justement sur le site du kit de stabilisation, j’ai compris que lorsque le laser se réchauffe, le gain est plus élevé pour une polarisation qu’une autre, ce qui fait qu’elle domine momentanément l’émission. Puisque le tube contenant le gaz est à l’intérieur d’un autre tube, ce réchauffement prend une éternité et est soumis aux variations des conditions environnementales (convection, etc.). L’idée de sliconsam (pseudo sur ebay) alias repairfaq.org, est de chauffer le tube en se régulant sur les valeurs des deux polarisations. Pour cela, il utilise un polarizing beam splitter cube orienté de manière à respecter l’orientation naturelle des deux modes du laser. Les instructions se trouvent ici : http://repairfaq.org/sam/manuals/stabins5.htm
Le schéma électronique est le suivant :
Une fois assemblé, ça ressemble à ceci :
J’ai rajouté un ampli transimpédance pour diminuer le bruit. Mon montage optique ressemble à un gros blob de colle, et fixé avec un tie-wrap sur le miroir du faisceau secondaire (ne le dites pas à personne, c’est un peu gênant).
La pièce imprimée en 3D est celle-ci, mais elle marchait moyen, c’était juste pour me donner une base :
Dans la version actuelle de ce kit, siliconsam fournit un pcb qui contient déjà cet assemblage un peu délicat. Mais toujours pas de manière de le fixer au tube. Bref mon montage n’est pas idéal, mais il fonctionne bien. Le résultat final ressemble à ceci (en incluant ma monture pour ajuster les angles et la hauteur déjà assemblée de mon projet d’interféromètre) :
En utilisant le firmware déjà présent sur l’arduino, qui contient entre autres un PWM (je n’ai pas lu tous les détails), j’ai réussi à observer l’évolution du réchauffement. On voit clairement une accélération de l’oscillation lorsque l’on part le heater, puis un ralentissement lorsque l’algo de stabilisation commence à embarquer.
Contrairement aux promesses, je n’ai pas réussi à obtenir un lock parfait, cela durait quelques minutes, puis le laser sortait de sa zone de stabilité et recommençait à osciller. Peut-être qu’il y a un bug, je vais essayer d’updater le firmware. Il y a aussi le fait que je l’ai utilisé en hiver avec une température externe démesurément basse de notre mois de janvier, dans une pièce propice aux courants d’air. En outre, le tube n’est pas isolé plus qu’il faut. Prochaine étape, faire un boitier pour tout ça qui isole mieux des conditions environnementales tout en permettant la flexibilité du montage. Peut-être que ça aiderait aussi le délai avant l’obtention d’un lock, qui était d’environ 45min-1h. Disons qu’il ne faut pas être pressé avant de faire des mesures! En tout cas, c’est très intéressant d’avoir un laser contrôlé en polarisation, pouvant fournir l’une ou l’autre sur demande, avec une stabilité en intensité qui dure plusieurs minutes.
Le mois passé, je suis tombé sur une boîte contenant du matériel optique que j’avais acheté au bac, inspiré par les laboratoires de Travaux pratiques d’optique photonique et de Fibre optique. Il y avait un paquet de lames quart d’onde en mica (spruce pine mica co part no 1000-0236), une paire de polariseurs circulaires provenant de lunettes de cinéma 3D, et une feuille de polariseur linéaire dichroique. Partant de ce matériel et d’un schéma rudimentaire du polarimètre de thorlabs :
je me suis dit que j’avais assez d’information en main pour construire mon propre polarimètre, pour la modique somme de pas mal moins que le 5861$US de la version de Thorlabs (ou encore 6750$US pour celui d’Edmund).
La complexité de l’optomécanique réside dans le fait que l’on veut faire tourner la lame quart d’onde selon son axe central, qui est aussi l’axe optique; autrement dit, l’axe de rotation doit être dégagé de tout matériel. C’est pas un requis très commun dans le monde de la mécanique et de la robotique. Après avoir investigué rapidement comment faire tourner un bearing sur lui-même sans grand succès, je suis tombé sur ce kit : Servocity Gear Drive Pan Kit for 37mm Spur Gear Motor. Il est vendu comme la base d’un systèm pan/tilt vertical (axe de rotation autour du z). La particularité est que l’axe central est un tube avec des bearings extérieurs, ce qui est parfait pour mon assemblage.
J’ai imprimé une première pièce pour coller ma lame quart d’onde avec de la colle blanche ordinaire :
La photodiode est branchée dans un ampli transimpédance au gain ajusté correctement avec une résistance. La sortie est envoyée à un analog input de l’arduino. Le sketch utilisé est simplement l’exemple Graph :
void setup() {
// initialize the serial communication:
Serial.begin(9600);
}
void loop() {
// send the value of analog input 0:
Serial.println(analogRead(A0));
// wait a bit for the analog-to-digital converter to stabilize after the last
// reading:
delay(2);
}
Avec le delay pour ajuster la fréquence d’échantillonage (ici, 500Hz). J’utilise la fonction traceur série intégré à l’IDE (outils -> traceur série)
Un moteur DC de 37mm de diamètre, 1100 rpm et 12V est utilisé avec une simple source de puissance à plusieurs voltages, ce qui permet de sélectionner sa vitesse. L’engrenage du système pan a un ratio 4.2:1 et j’opère le moteur à basse vitesse, environ 30rpm. Dû au couplage inconstant entre les engrenages et la friction, une petite variation dans la vitesse de rotation est observée, ce qui affecte la précision de la lecture de polarisation. Dans une version ultérieure, on pourrait utiliser un stepper qui fournirait une bien meilleure précision angulaire.
C’est un premier prototype pour identifier les défis à relever pour la suite. Dans un prochain article, je parlerai des mesures obtenues.