Le comparateur analogique des uC

Introduction aux entrées analogiques

La plupart des microcontrôleurs offrent la possibilité de mesurer les différences de potentiels. Cett opération de mesure exploite un convertisseur analogique/numérique pour convertir la différence de potentiels mesurée en une grandeur numérique codée sur N bits et proportionnelle à la différence de potentiels présente à l'entrée du convertisseur. Dans le cas de l'Arduino Uno et de son ATmega328p, la conversion s'opère sur 10 bits et exploite une structure de convertisseur à approximation successive. Cela signifie qu'il faudra un certain nombre de périodes d'horloge de conversion pour obtenir la valeur numérique.

La vidéo suivante apporte les explications de base sur la conversion analogique/numérique dans les microcontrôleurs et propose un premier exemple d'utilisation avec le framework Arduino.

Mesure de température avec une thermistance CTN

Composant très bon marché, la thermistance permet de mesurer la température avec une précision suffisante dans de très nombreuses situations et ce d'autant plus que sa forte non linéarité peut aisément être compensée par son exploitation judicieuse dans un diviseur de tension. La vidéo suivante s'intéresse à différentes possibilités de modélisation de la thermistance CTN (coefficient de température négatif = la résitance diminue lorsque la température augmente) : deux programmes Arduino sont également proposés pour la mise en oeuvre de ces modèles.

Pour ceux que cela intéresse, voici le code Scilab en vrac que j'ai utilisé pour tracer les caractéristiques :

PAS1 = 25;
PAS2 = 100
T25 = 25+273.15;
R25=10000;
B = 3950;
VCC = 5;
R0 = 10000;
clf;
T=-10+273.15:0.1:50+273.15;
//T=-2+273.15:0.1:12+273.15;
axeT = T-273.15;

// 1/T = 1/T25 + 1/B * ln(Rt/R25)
// B*(1/T - 1/T25) = ln(Rt/R25)
// R25*exp(B*(1/T - 1/T25)) = Rt
Rt = R25*exp(B*(1./(T) - 1/T25));
// Axis y1
cu=color("red");
plot2d(axeT,Rt,style=cu)
a = gca();
a.font_size = 3;  
xlabel("$T(" + char(176) + " C) = T-273.15$","FontSize",5)
ylabel("$Rt(T) = 10000.e^{\beta.(1/T - 1/(25+273.15))}$","FontSize",5,"Color", "red")
gca().children(1).children(1).thickness = 3;

//title("$Rt(T)$","FontSize", 5, "color","black")
xgrid(color("grey70")*[1 1])

Vt = R0./(R0+Rt);

// Axis y2
c=color("blue");
h2=newaxes();
h2.font_size = 3;
h2.font_color = c;
set(h2, "filled", "off", "foreground", c, "font_color", c);
plot2d(axeT,Vt,style=c)

h2.axes_visible(1)="off";
h2.y_location="right";
h2.children(1).children(1).thickness=3;
ylabel("$Vt(T)/V_{CC}$","FontSize",5,"color",c)
title("$Rt(T) \text{ et } Vt(T)/V_{CC}  \text{ et } \frac{1}{V_{CC}}.\frac{\partial Vt(T)}{\partial T}$","FontSize", 5, "color","black")
/*
waitClick();


//Vtprime = VCC*B*exp(B*(1./(T) - 1/T25))./((T.*(1+exp(B*(1./(T) - 1/T25))))^2);
Vtprime = R0*R25*B*exp(B*(1./(T) - 1/T25))./((T.*(R0+R25*exp(B*(1./(T) - 1/T25))))^2);

// Axis y3
c=color("darkgreen");
h3=newaxes();
h3.font_color=c;

plot2d(T-273.15,Vtprime,style=c)
h3.axes_visible(1)="off";
h3.filled="off";
h3.font_size = 3;
h3.y_location="middle";
h3.children(1).children(1).thickness=3;
ylabel("$\frac{1}{V_{CC}}.\frac{\partial Vt(T)}{\partial T}$","FontSize",5,"color",c, "position", [6 0.0105], "font_angle", 0)

function Vt = calcVt(T)
    T=T+273.15;
    Rt = R25*exp(B*((1/T) - (1/T25)));
    Vt = R25*VCC/(R25+Rt); 
endfunction

function waitClick()
    [%v0,%v1,%v2,%v3,%v4] = xclick();w = bool2s(%v0>64);
endfunction

waitClick();

// Animation
sca(a);
xstring(22, 54000, "$R_0=$");
gce.font_size = 6;
xstring(30.5, 54000, "$\Omega$");
gce.font_size = 6;
xstring(26, 54000, "10000");
t = get("hdl");
t.font_size = 6;

for R0 = 5000:PAS1:25000
    Vt = R0./(R0+Rt);
    Vtprime = R0*R25*B*exp(B*(1./(T) - 1/T25))./((T.*(R0+R25*exp(B*(1./(T) - 1/T25))))^2);
    
    h2.children(1).children(1).data = [T-273.15;Vt]';
    h3.children(1).children(1).data = [T-273.15;Vtprime]';
    //h3.ylabel("$\frac{1}{V_{CC}}.\frac{\partial Vt(T)}{\partial T}$","FontSize",4.5,"color",c, "position", [18 0.047])
    // Légende
    t.text = string(R0);
    sleep(3);
    if R0 == 10000 then
        waitClick();
    end
end

waitClick();

//*******************************************************************
//* Zoom sur la portion intéressante pour la sonde de réfrigérateur *
//*******************************************************************
clf;
R0=20000;
T=-2+273.15:0.1:12+273.15;


// 1/T = 1/T25 + 1/B * ln(Rt/R25)
// B*(1/T - 1/T25) = ln(Rt/R25)
// R25*exp(B*(1/T - 1/T25)) = Rt
Rt = R25*exp(B*(1./(T) - 1/T25));
// Axis y1
cu=color("red");
plot2d(T-273.15,Rt,style=cu)
a = gca();
a.font_size = 3;  
xlabel("$T(" + char(176) + " C) = T-273.15$","FontSize",5)
ylabel("$Rt(T) = 10000.e^{\beta.(1/T - 1/(25+273.15))}$","FontSize",5,"Color", "red")
gca().children(1).children(1).thickness = 3;

//title("$Rt(T)$","FontSize", 5, "color","black")
xgrid(color("grey70"))



Vt = R0./(R0+Rt);

// Axis y2
c=color("blue");
h2=newaxes();
h2.font_size = 3;
h2.font_color=c;

plot2d(T-273.15,Vt,style=c)
h2.axes_visible(1)="off";
h2.filled="off";
h2.y_location="right";
h2.children(1).children(1).thickness=3;
ylabel("$Vt(T)/V_{CC}$","FontSize",5,"color",c)
title("$Rt(T) \text{ , } Vt(T)/V_{CC} \text{ , } \frac{1}{V_{CC}}.\frac{\partial Vt(T)}{\partial T}$","FontSize", 5, "color","black")

//Vtprime = VCC*B*exp(B*(1./(T) - 1/T25))./((T.*(1+exp(B*(1./(T) - 1/T25))))^2);
Vtprime = R0*R25*B*exp(B*(1./(T) - 1/T25))./((T.*(R0+R25*exp(B*(1./(T) - 1/T25))))^2);

// Axis y3
c=color("darkgreen");
h3=newaxes();
h3.font_color=c;

plot2d(T-273.15,Vtprime,style=c)
h3.axes_visible(1)="off";
h3.filled="off";
h3.y_location="middle";
h3.children(1).children(1).thickness=3;
ylabel("$\frac{1}{V_{CC}}.\frac{\partial Vt(T)}{\partial T}$","FontSize",4.5,"color",c, "position", [18 0.047])


sca(a);
xstring(6, 36000, "$R_0=$");
gce.font_size = 6;
xstring(8.1, 36000, "$\Omega$");
gce.font_size = 6;
xstring(7, 36000, "10000");
t = get("hdl");
t.font_size = 6;

for R0 = 17000:PAS2:21000
    Vt = R0./(R0+Rt);
    Vtprime = R0*R25*B*exp(B*(1./(T) - 1/T25))./((T.*(R0+R25*exp(B*(1./(T) - 1/T25))))^2);
    

    h2.children(1).children(1).data = [T-273.15;Vt]';
    h3.children(1).children(1).data = [T-273.15;Vtprime]';
    //h3.ylabel("$\frac{1}{V_{CC}}.\frac{\partial Vt(T)}{\partial T}$","FontSize",4.5,"color",c, "position", [18 0.047])
    // Légende
    t.text = string(R0);
    waitClick();
end

// Coordonnées avec la souris
function souris_event(win, x, y, ibut)
  if ibut==-1000 then return,end
  [x,y]=xchange(x,y,'i2f')
  gcf().info_message = msprintf('Event code %d at mouse position is (%f,%f)',ibut,x,y);
endfunction


*/
sca(h2);
xstring(2, 0.5, "");
yt = get("hdl");
yt.font_size = 3;
//xstring(2, 0.4, "T=");
xt = get("hdl");
xt.font_size = 4;
while(1)
    xy = locate(1)
    yt.text = "T="+ string(xy(1)) + "      Vt/Vcc=" + string(xy(2));
    yt.data(1) = xy(1)-0.3;
    yt.data(2) = xy(2)+0.002; 
    //t.text = string(xy);
end



Interrupteur crépusculaire avec une photorésistance

On découvre aujourd'hui la photorésistance également appelée LDR pour Light Dependent Resistor. Objectif : allumer une LED lorsque la luminosité ambiante tombe sous un certain seuil.

Interrupteur crépusculaire géré par une machine à états

Les machines à états sont une réponse méthodologique pour gérer des processus plus ou moins complexes. Dans le cas de l'interrupteur crépusculaire qui reste une application simple, faire intervenir différentes conditions d'évolutions du système en fonction du temps et du niveau de luminosité conduit rapidement à une programmation manquant de lisibilité et de fiabilité sans utiliser de machine à états. Dans ce cas de figure, l'usage d'une machine à états évite également d'avoir recours à des structures bloquantes basées sur l'usage d'instruction délais de longues durées. La vidéo suivante expose la description d'une solution reposant sur une machine à états.