Charge et décharge du condensateur

Le montage que j’ai réalisé est en fichier joint avec le programme que j’ai écris mais il ne fonctionne pas

  1. Calculer la valeur de C pour avoir 5*RC = 2,5 s. pour la valeur du condo j’ai trouvé 100µF
  2. Ecrire un programme Arduino permettant de réaliser les consignes suivantes.
    •Lorsque l’utilisateur appuie sur le bouton poussoir, la broche D7 passe à HIGH pour une
    durée de 2,5 s. Le condensateur étant initialement déchargé, cela a pour effet de
    démarrer la charge. Après ce temps, la broche D7 passe à LOW ce qui a pour effet de
    décharger le condensateur. Durant cette phase, le programme acquière la tension aux
    bornes du condensateur qu’il envoie vers le port série avec la valeur de la tension de la
    broche D7 (5V ou 0V). L’envoi des données sur le port série se fera pendant 5 s (2,5 s pour
    la charge et 2,5 s pour la décharge).
    Cette valeur sera visualisée sous forme de graphe à l’aide du logiciel Processing.

Dans l’attente de votre aide je vous remercie d’avance

Arduino schéma montage condensateur.pdf (98.1 KB)

programme .txt (882 Bytes)

C'est quoi ça?

void loop() {
    void loop()

Bonsoir,

Il y a plusieurs erreurs dans ton progamme.

Tout d'abord les variables:
Après float vana = 0.0 il manque un ";".
byte etatCourant et unsigned long Timer, sont définies dans le setup() donc inconnues dans loop().

Ensuite, dans ta loop(), tu a un delay(2000), c.à.d. 2s, ce qui signifie que tu ne fait une mesure que toutes les deux secondes. Tu pourrais réduire le temps de boucle à 100mS, voire moins.

Et tu n'as pas initialiser ta liaison série avec la vitesse de transmission par un "Serial.begin()" dans le setup().

Et il ya certainement d'autres erreurs, mais corrige déjà toutes celles-ci.

bilbo83:
Bonsoir,

Il y a plusieurs erreurs dans ton progamme.

Tout d'abord les variables:
Après float vana = 0.0 il manque un ";".
byte etatCourant et unsigned long Timer, sont définies dans le setup() donc inconnues dans loop().

Ensuite, dans ta loop(), tu a un delay(2000), c.à.d. 2s, ce qui signifie que tu ne fait une mesure que toutes les deux secondes. Tu pourrais réduire le temps de boucle à 100mS, voire moins.

Et tu n'as pas initialiser ta liaison série avec la vitesse de transmission par un "Serial.begin()" dans le setup().

Et il ya certainement d'autres erreurs, mais corrige déjà toutes celles-ci.

Bonjour,

Merci de ton aide.

J'ai corrigé le programme et sa donne sa:

int vnum = 0;
float vana = 0.0;
byte etatCourant = LOW;
unsigned long Timer = 0;
void setup() {
Serial.Begin(9600);
}

void loop() {

unsigned long dateCourante = millis();
unsigned long intervalle = dateCourante - Timer;

if (etatCourant == LOW && intervalle > 2500) {

etatCourant = HIGH;
digitalWrite(7, etatCourant);
Timer = dateCourante;
}
else if (etatCourant == HIGH && intervalle > 2500) {

etatCourant = LOW;
digitalWrite(7, etatCourant);
timer = dateCourante;
}
//: Voltemetre
vnum = analogRead(A0);
vana = 5.0* (vnum/1024.0);
Serial.print("Valeur numérique : ");
Serial.print(vnum);
Serial.println(" sur 1024");
Serial.print("Valeur analogique : ");
Serial.print(vana);
Serial.println("V");
delay(2000);

}

Y-a-t'il d'autre erreurs ? et comment rajouter un "interrupteur" dans ce programme qui permet de faire ce qui est demandé dans mon premier post ?

Dans l'attente de votre aide je vous remercie d'avance.

Tu as toujours le delay à 2000, mets 100 pour tester.

Pour la conversion numérique/volt de vana:
Si tu veux être plus précis il faut que tu mesure la tension sur ta sortie 7 , ce ne sera certainement pas 5v exactement (ton circuit RC étant connecté).
Ensuite, ce n'est pas vnum/1024.0, c'est vnum/1023.0

Tu as également une mauvaise initialisation de Timer, au premier passage dans loop, millis()-Timer a une très forte probabilité d'être >2500. Ce n'est pas très grave, mais la solution est facile à trouver.

Précision:

Pour être conforme au réel, tu doit tenir compte de la mesure de la tension de sortie de la pin 7 à l'état haut (post précédent) mais également de la tension de sortie à l'état bas, ce ne sera certainement pas zéro.

corrigez votre post ci dessus et rajoutez les code tags autour du code:
[code]`` [color=blue]// votre code ici[/color] ``[/code].

ça doit ressembler à cela:// votre code ici
(faites aussi ctrl-T (PC) or cmd-T (Mac) dans l'IDE avant de copier le code pour qu'il soit indenté correctement)

bilbo83:
Tu as toujours le delay à 2000, mets 100 pour tester.

Pour la conversion numérique/volt de vana:
Si tu veux être plus précis il faut que tu mesure la tension sur ta sortie 7 , ce ne sera certainement pas 5v exactement (ton circuit RC étant connecté).
Ensuite, ce n'est pas vnum/1024.0, c'est vnum/1023.0

Tu as également une mauvaise initialisation de Timer, au premier passage dans loop, millis()-Timer a une très forte probabilité d'être >2500. Ce n'est pas très grave, mais la solution est facile à trouver.

J'ai fait une courbe avec un delay(100) cela ne change rien à la prise de mesure, ce qui gère la prise de mesure est le 2500 ms, en changeant 2500 ms par 100 ms la prise de mesure ce fait tout les 100 ms.

Je ne comprend pas a quoi sert le delay et pourquoi les 2500 ms gère et la prise de mesure alors que je voudrais qu'il gère le temps de maximum de la prise de mesure (2.5 s de charge et 2.5 s de décharge donc durée total de la prise de mesure de 5 s).

Dans l'attente de votre aide je vous remercie d'avance.

hello
avec 10ms, ca marche bien, les courbes sont jolies

j’ai rajouté un pic toutes les secondes pour avoir une échelle de temps

edit: suite au post ci dessus ( de_pépé_), la liaison est en 115200

dfgh:
hello
avec 10ms, ca marche bien, les courbes sont jolies

j'ai rajouté un pic toutes les secondes pour avoir une échelle de temps

edit: suite au post ci dessus ( de_pépé_), la liaison est en 115200

Bonjour,

J'ai le même programme et la courbe ne s'interrompt jamais et sa donne uniquement le chargement du condensateur (première partie de ta courbe qui dure indéfiniment).
Peut-tu m’envoyer ton programme s'il-te-plaît ?

Dans l'attente de votre aide je vous remercie d'avance.

je t’ncourage à regarder la fonction milis();

voici le code avec un while pour bloquer son exécution ( copie d’écran oblige)
et etat courant est un intermédiaire dont il est possible de se passer

int etatCourant = LOW;
int temps_charge = 2500;
unsigned long depart_charge = 0;
unsigned long fin_charge = 0;
int temps_decharge = 2500;
unsigned long depart_decharge = 0;
unsigned long fin_decharge = 0;
unsigned long ms = 0;
float charge = 0.0;
float decharge = 0.0;
void setup() {
  Serial.begin(115200);
  pinMode (7, OUTPUT); digitalWrite(7, LOW);
  pinMode (2, INPUT);
  pinMode (A0, INPUT);
}

void loop()
{
  if (!digitalRead(2))
  {
    etatCourant = HIGH;
    digitalWrite(7, etatCourant);
    depart_charge = millis();
    ms= millis();
    do
    { 
      fin_charge = millis();
      if((millis()-ms)>1000){ms= millis();Serial.println(1023);}
      charge = (analogRead(A0));
      Serial.println(charge);
      delay(10);
    } while ((fin_charge - depart_charge) < temps_charge);
  
    etatCourant = LOW;
    digitalWrite(7, etatCourant);
    depart_decharge = millis();
    ms= millis();
    do
    {
      fin_decharge = millis();
      if((millis()-ms)>1000){ms= millis();Serial.println(1023);}
      decharge = (analogRead(A0));
      Serial.println(decharge);
      delay(10);
    } while ((fin_decharge - depart_decharge) < temps_decharge);
    while(1);
  }
}

dfgh:
je t’ncourage à regarder la fonction milis();

voici le code avec un while pour bloquer son exécution ( copie d’écran oblige)
et etat courant est un intermédiaire dont il est possible de se passer

int etatCourant = LOW;

int temps_charge = 2500;
unsigned long depart_charge = 0;
unsigned long fin_charge = 0;
int temps_decharge = 2500;
unsigned long depart_decharge = 0;
unsigned long fin_decharge = 0;
unsigned long ms = 0;
float charge = 0.0;
float decharge = 0.0;
void setup() {
  Serial.begin(115200);
  pinMode (7, OUTPUT); digitalWrite(7, LOW);
  pinMode (2, INPUT);
  pinMode (A0, INPUT);
}

void loop()
{
  if (!digitalRead(2))
  {
    etatCourant = HIGH;
    digitalWrite(7, etatCourant);
    depart_charge = millis();
    ms= millis();
    do
    {
      fin_charge = millis();
      if((millis()-ms)>1000){ms= millis();Serial.println(1023);}
      charge = (analogRead(A0));
      Serial.println(charge);
      delay(10);
    } while ((fin_charge - depart_charge) < temps_charge);
 
    etatCourant = LOW;
    digitalWrite(7, etatCourant);
    depart_decharge = millis();
    ms= millis();
    do
    {
      fin_decharge = millis();
      if((millis()-ms)>1000){ms= millis();Serial.println(1023);}
      decharge = (analogRead(A0));
      Serial.println(decharge);
      delay(10);
    } while ((fin_decharge - depart_decharge) < temps_decharge);
    while(1);
  }
}

Merci, mais dans mon sujet on me demande d’utiliser un bouton poussoir en temps qu’interrupteur, comme les explication ci-dessous.

•Lorsque l’utilisateur appuie sur le bouton poussoir, la broche D7 passe à HIGH pour une
durée de 2,5 s. Le condensateur étant initialement déchargé, cela a pour effet de
démarrer la charge. Après ce temps, la broche D7 passe à LOW ce qui a pour effet de
décharger le condensateur. Durant cette phase, le programme acquière la tension aux
bornes du condensateur qu’il envoie vers le port série avec la valeur de la tension de la
broche D7 (5V ou 0V).

hello
oui et ton schéma dit bien que le BP est sur D2

chez moi, le BP est un bout de fil raccordé à gnd un court instant puis raccordé à +5V.
le prg fait le reste

D7 sur la résistance
A0 sur sur la borne + du condo

Merci à tous de m'avoir aider j'espère que ce sujet servira à d'autre personne.

Oui, tu as raison pepe, la datasheet du constructeur donne bien 1024 (vu pour un ATmega 2560).
Rien vue sur la doc de l'AT91SAM de la DUE que j'utilise plus couramment, mais je suppose que c'est pareil.
Cela ne me paraissais pas normal, mais bon, je vais bien lire la doc pour mieux comprendre.

On retrouve 1023 dans beaucoup de tutos et cela était plus conforme à mes habitudes.

Pour le 1023 ou 1024 c'est une Question de convention puisque de toutes façons vous faites un échantillonnage, donc la valeur lue sur la pin analogique représente un intervalle. Soit vous décidez de toujours prendre la borne basse de l'intervalle (division par 1024), soit vous affinez un peu arbitrairement pour en valeur basse prendre le début de l'intervalle, en valeur médiane, le milieu de lintervalle et en valeur haute le haut de l'intervalle (division par 1023); vraiment c'est une question de choix personnel je pense et je préfère 1023 ici

Si Vous faites

vnum = analogRead(A0); // une valeur ente [0 .. 1023]
vana = 5.0* (vnum/1024.0); // une valeur entre [0 .. 5[ (mais pas 5)

--> En divisant par 1024 vous n'aurez jamais 5v atteint, même si vous branchez la Pin a0 sur 5v. Moi ça m'énerve :slight_smile:

en faisant

vnum = analogRead(A0); // une valeur ente [0 .. 1023]
vana = 5.0* (vnum/1023.0); // une valeur entre [0 .. 5]

Là vous aurez bien 5V tout rond quand vous lisez 1023 et si vous branchez A0 sur GND vous aurez bien 0V. Je trouve ça plus Sympa.

Je ne suis pas d'accord - vous n'avez rien de plus rigoureux à représenter par un nombre unique un intervalle avec 1024 plutôt que 1023. Prendre toujours la borne inférieure revient à toujours sous estimer la mesure, prendre toujours la borne supérieure à toujours la surestimer.

comme vous le dites la valeur correspond réellement à un intervalle et donc choisir arbitrairement (par une bijection) une valeur dans cet intervalle est un choix pas plus faux qu'un autre pour une mesure unitaire.

Comme je l'explique dans le cas présent considérerer une interpolation linéaire de la valeur à retenir dans cet intervalle est une décision mathématique tout aussi respectable qu'une autre qui a l'avantage pour moi de donner 0v et 5v en sortie quand vous avez 0V et 5v en entrée, d'où ma préférence.

(On est d'accord sur l'efficacité avec 1024 versus 1023)

Dans le cas présent je suis d'accord avec pepe parce qu'à mon avis le choix a déjà été fait par le concepteur de l'ADC du micro.

Vous vous battez pour 1 pas, c'est à dire du 1 pour 1000.
Si on voulait être rigoureux et tenir de toutes les erreurs telles qu'elles sont décrites dans la datasheet on se retrouve avec une précision au mieux de +/- 5 pas.

La principale difficulté avec les indications de la datasheet est de distinguer les erreurs systématiques pour un exemplaire donné, qui se somment directement, des erreurs aléatoires qui se somment sous forme quadratique (racine de la somme des carrés).

Ma conclusion : si j'avais à faire des mesures précises où un pas compte je n'utiliserai surrement pas le module ADC intégré à un microcontrôleur.
L'ADC du microcontrôleur est bien pratique mais il ne faut pas lui demander plus qu'il ne peut donner.

on se retrouve avec une précision au mieux de +/- 5 pas.

C'est un peu mon point.... ici il ne s'agit pas de cumuler des valeurs et de dérive donc de la précision / accumulation de l'erreur. il s'agit d'un affichage instantané.

Tout ce que je dis c'est qu'afficher 0V quand vous branchez sur GND et 5V quand vous branchez sur la référence 5V c'est quand même plus gratifiant et pas plus faux que d'afficher 0V et 4,995...

D'un point de vue pratique, il faut différencier ce que l'on fait en affichage (conversion en flottant) versus les calculs numériques où mon approche est de rester avec les entiers entre 0 et 1023 (ou d'utiliser de CAN de meilleure facture)

Je n'en ai pas grand chose à faire de l'affichage instantané, je n'ai jamais fait de mesure avec un affichage instantané !

Ce qui compte quand on fait des mesures c'est bien la valeur "probable" avec sa marge d'erreur.

Je sais que dans les écoles on n'apprend plus à faire un calcul d'erreur et que tout ce qui est affiché avec des valeurs numériques est maintenant pris pour argent comptant.

L'important est de bien d'ouvrir les yeux de ceux qui croient que l'ADC d'un micro avr est juste à un pas près.
Je me fiche de lire 0 ou 1 car je sais que les deux sont très probablement faux ->je suis un électronicien de terrain donc avec les pieds sur terre.

Le reste me parrait secondaire surtout que je suis persuadé que tout a déjà figé par Atmel.