Partage
  • Partager sur Facebook
  • Partager sur Twitter

capteur de courant ACS712 20A

Sujet résolu
7 juin 2017 à 7:47:22

Bonjour je pense avoir un problème avec le capteur ACS712 20A.
J'ai crée une prise électrique connectée et je veux lui ajouter une fonctionnalité : calculer la consommation de courant électrique de n'importe quel appareil branché.
J'ai trouvé beaucoup de code différents sur le net, j'ai "mixé" selon ce que je pensais être correct et voici celui que j'utilise :

// Libraries required for Wifi connection
#include <Wire.h>
#include <UnoWiFiDevEd.h>

float amplitude_current;
float effective_value;
float effective_voltage = 100; // Set voltage to 230V (Europe) or 110V (US)
float effective_power;
float zero_sensor;
float power;

void setup()  { //Initialization loop
    pinMode(13,OUTPUT); //Signals to the Arduino that connection 13 must be able to send current
    Wifi.begin(); //Initializes the network settings of the Wi-Fi library
    Wifi.println("Web Server is ok"); //Display when the web server has started
    zero_sensor = getSensorValue(A0);
    Serial.begin(9600);
}
void loop() { //Infinite loop

    while(Wifi.available())  { //as long as wifi reading is available
      readUrl(Wifi); //call to the readUrl function
    }
    
    delay(50); //50ms pause

    // Perform power measurement
  float sensor_value = getSensorValue(A0);
    
  // Convert to current
  amplitude_current = (float)(sensor_value-zero_sensor)/1024*5/100*1000000;
  effective_value = amplitude_current/1.414;
  effective_power = abs(effective_value*effective_voltage/1000);

Serial.print("\n amplitude current = ");
Serial.print(amplitude_current,2);  
Serial.print("\t effective_value = ");  
Serial.print(effective_value,2);  
Serial.print("\t Power (W) = ");
Serial.print(effective_power,2);  
delay(1000);

}

// Get the reading from the current sensor
float getSensorValue(int pin)
{
  int sensorValue;
  float avgSensor = 0;
  int nb_measurements = 1000;
  for (int i = 0; i < nb_measurements; i++) {
    sensorValue = analogRead(pin);
    avgSensor = avgSensor + float(sensorValue);
  }    
  avgSensor = avgSensor/float(nb_measurements);
  return avgSensor;
}

J'ai cependant des valeurs étranges. Par exemple, peu importe l'appareil branché à la prise, la puissance est toujours approximativement égale à :

amplitude current = -59.91 effective_value = -42.37 Power (W) = 4.66
amplitude current = -56.54 effective_value = -39.99 Power (W) = 4.40
amplitude current = -52.10 effective_value = -36.85 Power (W) = 4.05
amplitude current = -69.43 effective_value = -49.10 Power (W) = 5.40
amplitude current = -69.34 effective_value = -49.03 Power (W) = 5.39
amplitude current = -53.32 effective_value = -37.71 Power (W) = 4.15
amplitude current = -50.34 effective_value = -35.60 Power (W) = 3.92
amplitude current = -55.76 effective_value = -39.44 Power (W) = 4.34
amplitude current = -41.60 effective_value = -29.42 Power (W) = 3.24
amplitude current = -58.25 effective_value = -41.20 Power (W) = 4.53
amplitude current = -55.13 effective_value = -38.99 Power (W) = 4.29

Alors qu'elle devrait être égale à (lorsque mon ordinateur est branché) : 0.33Amp et 17 à 25 Watts
Quelqu'un peut il m'aider svp ? Vous pouvez trouvez le schéma de mon projet. Merci

-
Edité par Mouk Bouk 7 juin 2017 à 7:48:40

  • Partager sur Facebook
  • Partager sur Twitter
7 juin 2017 à 8:41:51

Le capteur ACS712 sort une tension typique de 2.5V + 66mV par ampères.

Si tu connaitre le courant, il faut donc soustraire ces 2.5V puis appliquer le facteur 66mV/A.

Pour ta formule, tu as bien fais la soustraction avec (sensor_value-zero_sensor) sauf que ta variable zero_sensor est calculé à l'initialisation par zero_sensor = getSensorValue(A0);

Du coup, au démarrage de ton arduino, celui-ci fait une mesure qu'il considèrera comme le point de fonctionnement de 0A donc il faut impérativement qu'il n'y ai rien de branché lorsque l'arduino démarre (après avoir téléversé le code et/ou mise sous tension de l'arduino).

As tu bien pensé à débrancher ton PC après téléversement ? J'en doute ;)

Si tu ne l'as pas fais, ton code va afficher une valeur proche de 0.

Peut-être ferais tu mieux d'initialiser ta variable zero_sensor à 2047 qui correspond à la valeur théorique de l'ADC de l'arduino pour du 2.5V.

------------------------------

Tu risques aussi d'avoir un problème de moyenne.

En effet, sur une charge passive (une lampe par exemple), le courant est alternatif à 50 Hz et change donc constamment sur une belle sinusoïde.

Et quand il s'agit d'une alimentation à découpage de PC, la consommation est encore plus aléatoire avec des pics, des creux et une consommation très certainement plus importante sur le haut de la sinus si celle-ci ne possède pas de PFC.

Faire 1000 mesures n'est pas forcément très judicieux si tu ne métrise pas le temps entre chaque mesure.

Et comme le courant va dans un sens puis dans l'autre (EDF délivre une tension alternative), la moyenne du courant est forcément nulle.

Tu ferais mieux de faire une mesure toutes les 0.1ms pendant 1 secondes (soit 10.000 mesures) et faire la moyenne du courant absolue.

------------------------------

Quand à la puissance, si tu ne mesures pas la tension, ce ne pourra pas être très précis.

En France, on est censé être en 230V mais ça varie de 220 à 240 suivant les régions et ta proximité avec une centrale.

-
Edité par lorrio 7 juin 2017 à 8:44:26

  • Partager sur Facebook
  • Partager sur Twitter
8 juin 2017 à 7:24:04

Bonjour et merci pour votre réponse,
je me trouve actuellement au Japon c'est pourquoi je laisse la variable effective_voltage=100;
Je vous résume tout d'abord mon projet, mon schéma est composé de la manière suivante :

Ma multiprise est branché à une prise terre (normale) qui délivre une tension de 100V.
A cette multiprise est relié le relai qui est également branché à l’Arduino.
Le capteur de courant est quant à lui relié au relai mais également au la multiprise.

Vous pouvez trouvez des images de montage de mon projet au lien suivant :

https://drive.google.com/open?id=0BylxxJeKtzdycXVCZkpPZjlENkk

Mon but est donc de calculer la consommation de courant électrique de n'importe quels appareil branché sur cette multiprise.
Il faut donc que je trouve l'intensité du courant électrique pour me permettre de calculer la puissance (en watts) ce qui est plus intéressant pour l'utilisateur.
Je ne sais pas comment faire pour calculer moi-même la tension pour une meilleur précision.

Mon capteur de courant ACS712 est un mode 20A donc d'après le datasheet le facteur est 100mvA il me semble.

J'ai également fait attention au fait de ne rien branché au démarrage de l’Arduino et juste après avoir téléversé le code. Le nombre de mesure est aussi passé à 10 000 et j'ai bien appliqué la valeur 2047 a zero_sensor.

Cependant les résultats que j'obtiens son toujours incorrect, je ne comprend pas pourquoi.

  • Partager sur Facebook
  • Partager sur Twitter
8 juin 2017 à 12:43:39

C'est ce que je te disais à propos de la moyenne.

De courant étant alternatif, il est une fois positif, une fois négatif.

Du coup, si tu fais une moyenne du courant, tu vas forcément trouver quelque chose proche de 0.

Il te faut faire la moyenne des valeurs absolues pour que cela fonctionne.

Par contre, j'ai fais une erreur sur la valeur 2047...

L'ADC de l'arduino étant en 10bits, sa valeur milieu de 2.5V est de 512 et non 2047.

Essayes cette fonction qui devrait théoriquement te donner le courant en ampère :

float getCurrentValue(int pin) {
	
	int absVal;
	long int absSum = 0;
	float current;
	
	for ( int i = 0 ; i < 20000 ; i++ ) {
		
		absVal = analogRead(pin);
		absVal = ( absVal - 512 );
		absVal = ( ( absVal >= 0 ) ? ( absVal ) : ( -absVal ) );
		
		absSum = ( absSum + absVal );
		
		delayMicroseconds(50);
		
	}
	
	current = ( (float)absSum );
	current = ( current / 20000.0 );				// Division par le nombre d'éléments
	current = ( ( current * 5.0 ) / 1024.0 );		// Conversion en volt (ADC 10bits=1024pts, ref 5.0V)
	current = ( current * 10.0 );					// Conversion en ampères (ACS712-20A: 100mV/A=10A/V)
	
	return current;
	
}

Mais pourquoi ne pas acheter directement ce genre d'appareil tout prêt ?

Un wattmètre, ça coute une vingtaine d'euros, ça mesure la tension et le courant avec plus de précision que l'arduino et ça calcul tout un tas d'autre paramètres (puissance, consommation, facteur de puissance...)

Au final, ces 20€ investit dans cette appareil reviennent pratiquement aussi chère que d'acheter arduino+ACS712+alim sauf qu'on a un vrai appareil plus fiable, moins dangereux, plus précis...

https://www.amazon.fr/WATTM%C3%88TRE-Compteur-dEnergie-230V-16A/dp/B001CZ5HCI



-
Edité par lorrio 8 juin 2017 à 12:48:49

  • Partager sur Facebook
  • Partager sur Twitter
9 juin 2017 à 7:18:21

Bonjour et merci pour votre réponse, voici le nouveau code que j'ai adapté

// Libraries required for Wifi connection
#include <Wire.h>
#include <UnoWiFiDevEd.h>

float amplitude_current;
float effective_value;
float effective_voltage = 100; // Set voltage to 230V (Europe) or 110V (US)
float effective_power;
float zero_sensor;
float power;

void setup()  { //Initialization loop
    pinMode(13,OUTPUT); //Signals to the Arduino that connection 13 must be able to send current
    Wifi.begin(); //Initializes the network settings of the Wi-Fi library
    Wifi.println("Web Server is ok"); //Display when the web server has started
    zero_sensor = 512;
    Serial.begin(9600);
}
void loop() { //Infinite loop

    while(Wifi.available())  { //as long as wifi reading is available
      readUrl(Wifi); //call to the readUrl function
    }
    
    delay(50); //50ms pause


  float sensor_value = getCurrentValue(A0);
    
  amplitude_current = (float)(sensor_value-zero_sensor)/1024*5;
  effective_value = amplitude_current/1.414;
  effective_power = abs(effective_value*effective_voltage/1000);


  Serial.print("\n amplitude current = "); 
  Serial.print(amplitude_current,2);  
  Serial.print("\t effective_value = ");   
  Serial.print(effective_value,2);   
  Serial.print("\t Power (W) = "); 
  Serial.print(effective_power,2);  
  delay(50);

}

float getCurrentValue(int pin) {
     
    int absVal;
    long int absSum = 0;
    float current;
     
    for ( int i = 0 ; i < 20000 ; i++ ) {
         
        absVal = analogRead(pin);
        absVal = ( absVal - 512 );
        absVal = ( ( absVal >= 0 ) ? ( absVal ) : ( -absVal ) );
         
        absSum = ( absSum + absVal );
         
        delayMicroseconds(50);
         
    }
     
    current = ( (float)absSum );
    current = ( current / 20000.0 );                // Division par le nombre d'éléments
    current = ( ( current * 5.0 ) / 1024.0 );       // Conversion en volt (ADC 10bits=1024pts, ref 5.0V)
    current = ( current * 10.0 );                   // Conversion en ampères (ACS712-20A: 100mV/A=10A/V)
     
    return current;
}



 J'ai également pris en compte de débrancher le pc après téléversement etc...

J'ai cependant toujours des erreurs :

Lorsque j'applique zero_sensor=512; voici les résultats que j'obtiens :

 amplitude current = -2.50     effective_value = -1.77     Power (W) = 0.18
 amplitude current = -2.50     effective_value = -1.77     Power (W) = 0.18

et ça ne varie pas peu importe si je branche n'importe quel appareil.

Lorsque j'applique zero_sensor=getCurrentValue(A0); les résultats sont tous nuls et de même aucune variation.

Je ne comprend pas pourquoi. 

Je suis en stage et c'est donc un projet. J'ai cependant à ma disposition un wattmètre qui me permet de savoir quels valeurs je dois obtenir. Pour mon pc par exemple je devrais obtenir en moyenne :

100V | 0.30~0.50Amp | ~30Watt

Merci

  • Partager sur Facebook
  • Partager sur Twitter
9 juin 2017 à 8:19:24

As tu pris le temps de bien lire et comprendre l'ensemble de mon message et du code proposé ?

lorrio a écrit:

Essayes cette fonction qui devrait théoriquement te donner le courant en ampère :

La fonction que je t'ai proposé te donne directement le résultat en ampère.

Tu n'as donc pas de soustaction pas 512 à faire sur ce résultat, ni division, multiplication et autre.

Essayes d'afficher directement le résultat et ajuste un peu si besoin.

-
Edité par lorrio 9 juin 2017 à 8:20:00

  • Partager sur Facebook
  • Partager sur Twitter
9 juin 2017 à 9:10:23

Je viens de le tester tel que ci-dessous :

// Libraries required for Wifi connection
#include <Wire.h>
#include <UnoWiFiDevEd.h>


void setup()  { //Initialization loop
    pinMode(13,OUTPUT); //Signals to the Arduino that connection 13 must be able to send current
    Wifi.begin(); //Initializes the network settings of the Wi-Fi library
    Wifi.println("Web Server is ok"); //Display when the web server has started
    Serial.begin(9600);
}
void loop() { //Infinite loop
    
    delay(50); //50ms pause

  // Perform power measurement

  float amplitude_current = getCurrentValue(A0);
    
  Serial.print("\n amplitude current = "); 
  Serial.print(amplitude_current,2);  

  delay(50);

}

float getCurrentValue(int pin) {
     
    int absVal;
    long int absSum = 0;
    float current;
     
    for ( int i = 0 ; i < 20000 ; i++ ) {
         
        absVal = analogRead(pin);
        absVal = ( absVal - 512 );
        absVal = ( ( absVal >= 0 ) ? ( absVal ) : ( -absVal ) );
         
        absSum = ( absSum + absVal );
         
        delayMicroseconds(50);
         
    }
     
    current = ( (float)absSum );
    current = ( current / 20000.0 );                // Division par le nombre d'éléments
    current = ( ( current * 5.0 ) / 1024.0 );       // Conversion en volt (ADC 10bits=1024pts, ref 5.0V)
    current = ( current * 10.0 );                   // Conversion en ampères (ACS712-20A: 100mV/A=10A/V)
     
    return current;
}

 Lorsque aucun appareil branché j'obtiens dans le moniteur série :

 amplitude current = 0.13
 amplitude current = 0.13
 amplitude current = 0.12
 amplitude current = 0.12

Lorsque je branche un appareil :

 amplitude current = 0.77
 amplitude current = 0.83
 amplitude current = 0.83

Lorsque je débranche l'appareil :

 amplitude current = 0.77
 amplitude current = 0.83
 amplitude current = 0.83

D'après mon wattmètre, le résultat attendu devrait être proche de ~0.3Amp

  • Partager sur Facebook
  • Partager sur Twitter
9 juin 2017 à 11:35:57

Quand tu débranches ton appareil, le courant ne redescend pas ???

Là, il pourrait être intéressant de tester ton capteur pour voir moyenne/min/max qu'il donne.

Dis nous ce que ce code affiche avec rien de branché et ce qu'il donne avec ton PC branché :

void loop() {

	int val;
	int min = 1024;
	int max = 0;
	long int sum = 0;
	int avg;

	for ( int i = 0 ; i < 20000 ; i++ ) {

		val = analogRead(A0);

		if ( val > max ) {
			max = val;
		}
		if ( val < min ) {
			min = val;
		}

		sum += val;

		delayMicroseconds(50);

	}

	avg = ( sum / 20000 );

	Serial.print("min=");
	Serial.print(min);
	Serial.print(", ");
	Serial.print("max=");
	Serial.print(max);
	Serial.print(", ");
	Serial.print("sum=");
	Serial.print(sum);
	Serial.print(", ");
	Serial.print("avg=");
	Serial.print(avg);
	Serial.println();

	delay(100);

}

      



-
Edité par lorrio 9 juin 2017 à 11:37:31

  • Partager sur Facebook
  • Partager sur Twitter
9 juin 2017 à 12:51:41

Non quand je débranché rien ne redescendais

rien branché :

min=506, max=514, sum=10191660, avg=509
min=506, max=513, sum=10191435, avg=509
min=506, max=514, sum=10191660, avg=509

pc branché :

min=448, max=547, sum=9948585, avg=497
min=448, max=549, sum=9957376, avg=497
min=449, max=548, sum=9964211, avg=498
min=452, max=547, sum=9970870, avg=498
min=446, max=551, sum=9975786, avg=498
min=445, max=556, sum=9975416, avg=498
min=445, max=557, sum=9973726, avg=498
min=441, max=555, sum=9976663, avg=498

pc débranché après l'avoir branché :

min=455, max=548, sum=10026185, avg=501
min=498, max=506, sum=10042308, avg=502
min=499, max=507, sum=10051556, avg=502
min=499, max=506, sum=10053483, avg=502

  • Partager sur Facebook
  • Partager sur Twitter
10 juin 2017 à 22:20:37

Tes premières mesures sont plutôt logique.

Quand il n'y a pas de courant, ton capteur doit donner une valeur théorique de 512, ce qui correspond bien au min/max entre 506 et 514 que tu as.

Sachant que l'ADC et le 5V de l'arduino ne sont clairement pas parfait, c'est logique qu'il y ai une petite oscillation pas forcément centrée sur 512.

Quand tu branches ton PC, on va qu'il y a du courant qui circule dans un sens puis dans l'autre puisque les valeurs min/max s'éloigne beaucoup du 512 avec une plage 440, 560 environ.

Et quand tu débranches à nouveau ton PC, cela revient autours de 512 avec une plage min/max entre 500 et 505 (et donc un courant faible).

Du coup, je serais d'avis de dire que ton capteur marche, c'est plutôt bon signe ;)

Par contre, on voit clairement que la précision du 0 ampère n'est pas génial car la moyenne n'est pas de 512 et change dans le temps (509 avant de branché, 501 après avoir débranché).

  • Partager sur Facebook
  • Partager sur Twitter
11 juin 2017 à 6:46:49

Ok, je prend note merci.

Du coup j'ai toujours pas compris comment est-il possible qu'avec la fonction getCurrentValue() lorsque aucun appareil est branché elle m'affiche:

amplitude current = 0.13

Lorsque je branche un appareil :

 amplitude current = 0.77
 amplitude current = 0.83
 amplitude current = 0.83

Lorsque je débranche l'appareil :

 amplitude current = 0.77
 amplitude current = 0.83
 amplitude current = 0.83

Qu'est ce qu'il y a à changer ? Ou est l'erreur puisque mon capteur semble fonctionner ?

Comment améliorer cette précision 0 ampère ?

-
Edité par Mouk Bouk 11 juin 2017 à 6:48:33

  • Partager sur Facebook
  • Partager sur Twitter
11 juin 2017 à 12:25:46

Pour améliorer cette précision, tu peux faire un étalonnage.

C'est à dire faire plusieurs mesures mesures au début de ton programme avec aucun appareil branché de façon à voir la valeur donnée par le capteur pour soustraire cette valeur au lieux de soustraire 512.

Tu peux aussi refaire l'étalonnage du 0A dynamique pendant l'exécution du programme avec un algorithme du genre : "si la valeur min/max reste entre 502 et 522 pendant pendant plus de 3 secondes, alors on considère que la valeur moyenne correspond au 0 ampères".

Ainsi, le simple fait de n'avoir aucun appareil qui consomme pendant plus de 3 secondes remettra correctement ton capteur à 0.

  • Partager sur Facebook
  • Partager sur Twitter
12 juin 2017 à 4:01:10

Ok et donc une fois l'étalonnage réalisé, je pourrais utiliser la fonction getCurrentValue() (en remplacant le -512 par la valeur que j'ai trouvé) sans problème ?

Par contre je ne vois pas trop comment réaliser cet étalonnage du 0A dynamique, auriez-vous des pistes svp ?

  • Partager sur Facebook
  • Partager sur Twitter
12 juin 2017 à 8:23:02

Sans problème, je ne sais pas... disons que ça ne peut que améliorer les choses.

Dans tous les cas, il te faut faire un mixte des 2 programmes.

Garder une partie du premier pour avoir la mesure du courant en ampère.

Et ajouter aussi le deuxième pour obtenir min/max/moyenne.

Tu devras aussi avoir une variable qui te sert de compteur pour effectuer les actions suivantes :

- si courant proche de 0A, on incrémente (min/max entre 502 et 522 par exemple)

- si courant loin de 0A, on remet le compteur à 0

- le le compteur dépasse 3, la valeur moyenne correspond au 0A

-
Edité par lorrio 12 juin 2017 à 8:23:44

  • Partager sur Facebook
  • Partager sur Twitter
7 juillet 2020 à 23:55:00

Bonjour ,sil vous plait je besoin vous aide ,
  • Partager sur Facebook
  • Partager sur Twitter
8 juillet 2020 à 8:01:07

J'ai un peu de mal à voir comment on va pouvoir faire pour t'aider si tu ne prends même pas le temps de décrire ton problème.

Plutôt que de déterrer un vieux sujet marqué résolu, je t'invite à créer ton propre nouveau sujet dans lequel tu nous expliques un peu ce que tu as besoin comme aide.

Sur ceux, je ferme.

  • Partager sur Facebook
  • Partager sur Twitter