Beruflich Dokumente
Kultur Dokumente
EL ACS712.
Fig. 1
El espesor de la pista de cobre permite la supervivencia del dispositivo en
hasta 5 × condiciones de sobre corriente. Los terminales de la pista
conductora están eléctricamente aislados de los cables de los sensores
(pines 5 a 8 en fig. 2). Esto permite que el sensor de corriente ACS712
para ser utilizado en aplicaciones que requieren aislamiento eléctrico sin
el uso de aisladores ópticos u otras técnicas de aislamiento costosas.
Mi idea inicial era realizar un voltímetro para que lo utilice quien quiera y
pueda aplicarla a su fuente de alimentación. Pensé que con este elemento
se completaría un dispositivo importante en una fuente de laboratorio, y
por ese motivo realicé un artículo que describe como aplicar un voltímetro a
cualquier fuente de alimentación.
Una vez empecé el artículo y a medida que avanzaba me di cuenta que si
además de voltímetro midiera la corriente de consumo, estaría más
completo y de esta forma tuve que adquirir uno de estos dispositivos, y esa
es la razón de este artículo. El esquema práctico de conexionado es
sencillo y fácil de entender. Se trata de conectar el sensor en serie con la
carga que queremos conocer la corriente de consumo.
Fig. 2
Tensión de salida en reposo (Viout (Q)). La salida del sensor cuando la
corriente primaria es cero. Para una tensión de alimentación unipolar,
sigue siendo nominalmente VCC / 2. Por lo tanto, cuando no hay
corriente la tensión de salida es VCC / 2 = 5 V / 2 = 2.5V. La variación en
Viout (Q) se pueden atribuir a la resolución de la compensación de tensión
de reposo IC Allegro lineal y la deriva térmica. Parece muy complicado, lo
intentaré más sencillo.
Cuando no haya corriente de paso por el sensor, leerá CERO, pero esto
no va a dar cero en las lecturas. Me voy a explicar, los puertos analógicos
en Arduino utilizan un conversor A/D que va de 0 a 1023, donde el 0 == 0
V y el 1023 == 5 V, como el sensor es bidireccional, cuando el sensor no
detecta corriente el voltaje será de 2,5 V = (VCC / 2) y la lectura de Arduino
será algo cercano a 512. Por lo tanto, si la corriente es positiva va a
aumentar la lectura y una lectura negativa la disminuirá.
Fig. 3
Para comprender mejor esto, supongamos que este sensor mide
intensidades entre -5A y +5A (vea su modelo que alcance tiene). Ya que
la salida del sensor según la hoja de datos siempre entrega entre 0 y 5
voltios, cuyo valor de 0A se corresponde con los 2.5V en la salida, y por
cada amperio la tensión varía 185 mA. Este sensor puede medir tanto CC
como CA, si vemos una sinusoide, el punto más bajo se corresponde con
los -5A, de modo que los 2.5V de salida corresponden justo a 0A y los +5A
con los 5V, véase la imagen que sigue.
Fig. 4
Espero que haya quedado claro. El modo de conexionado se muestra
simbólicamente en la figura siguiente.
Fig. 5
DESCRIPCIÓN.
Fig. 6
De hecho, la aplicación en modo amperímetro se puede entender como tal
ya que se conecta en serie con la carga. Por el momento sólo lo he
probado en corriente continua y con corrientes de unos pocos amperios.
Fig. 7
El próximo paso es adecuar en lo posible el código y mostrar los
resultados en una pantalla LCD numérica, la misma que nos mostrará la
tensión de salida en cada momento. Veamos algunos aspectos que
tenemos que adjuntar al código, como es la librería ‘LiquidCrystal.h‘ que
debemos descargar la última versión para evitar sorpresas. Copie y pegue
el siguiente código en su Arduino, dele el nombre amp_acs712.ino, cárgelo
y abra el monitor Serial, compruebe que el resultado es más preciso.
El esquema que vamos a utilizar es el siguiente.
Fig. 8
Estos son los datos que he extraído del código anterior. Con este código
se puede implementar el voltímetro junto con el LCD y podemos utilizarlo
de forma habitual, sin embargo, intentaremos realizar un código más
completo en el siguiente intento.
Por lo tanto, sólo nos queda añadir nuestro típico LCD de 2 o 4 líneas, en
mi caso dispongo del 2004A de 4 líneas que es el que voy a utilizar. He
mejorado el circuito y la disposición en la PCB como se puede apreciar,
especial atención a las masas resaltadas en la imagen. En este momento,
el montaje se hará con el Arduino, posteriormente debería utilizarse un
Attiny85.
Fig. 12
Ahora, veamos que ve nuestro pin analógico A0, sí la lectura ADC es 615,
la tensión en pin A0 = 0.004887 * lectura ADC (615 en este caso), o sea
3,0V. Del mismo modo:
Para 1V / 0.00488 = 205 (ADC lectura – redondeando hacia arriba) … y
Para 4V / 0.00488 = 820 (ADC lectura – redondeando hacia arriba)
[El ADC en un AVR no puede medir de forma muy precisa las señales
con una alta impedancia de salida, y un divisor de tensión sin duda
cuenta con una alta impedancia. A partir de la hoja de datos
ATmega328P:
Esta es la parte más importante del proyecto como es el código que mide
voltios, amperios.
1 /*
2 * volt_amp_watt.pde
3 *
4 * http://arduinotronics.blogspot.com.es/2014/01/volt-amp-watt-hour-meter-shield.html
5 *
6 * Hace un tiempo que he diseñado un medidor de vatios hora para el seguimiento de la
7 * energía producida por energía solar o eólica, consumida por las cargas, y la potencia
8 * contenida en un banco de baterías. He producido una nueva versión basada en la Sparkfun
9 * Protoshield. Éste utiliza un sensor de corriente ACS712 (5 amperios), y está diseñado
10 * para controlar hasta 10 VDC. Diferentes sensores y resistencias actuales se pueden
11 * instalar para otros rangos de corriente y tensión. La próxima actualización será una
12 * cabecera de 16 pines para una pantalla LCD. Así que estad atentos. Código y esquemas de
13 * cableado próximamente.
14 */
15
16 #include <LiquidCrystal.h> // lib. LiquidCrystal.h
17
18 //LiquidCrystal lcd(12, 11, 10, 9, 8, 7);
19 //LCD: (RS, E,D4,D5,D6,D7)
20 LiquidCrystal lcd(8, 7, 6, 5, 4, 3); // mi config.
21
22 const float referenceVolts = 5; // the default reference on a 5-volt board
23 //const float referenceVolts = 3.3; // use this for a 3.3-volt board
24
25 const float R1 = 47000; // value for a maximum voltage of 30 volts
26 const float R2 = 9430;
27 // determine by voltage divider resistors, see text
28 const float resistorFactor = 1023.0 / (R2/(R1 + R2)); // ratio
29 const int batteryPin = A0; // +V from battery is connected to analog pin A0
30
31 int sensorPin3 = A1; // select the input pin for the potentiometerpin input Volt
32
33 int sensorValue0 = 0; // variable to store the value coming from the sensor
34 int sensorValue3 = 0; // variable to store the value coming from the sensor
35
36 void setup() {
37 // initialize Serial communication at 9600 bits per second:
38 Serial.begin(9600);
39 lcd.begin(20,4); // columns, rows. use 16,2 for a 16x2 LCD, etc.
40 lcd.setCursor(0,0); // set cursor to column 0, row 0 (the first row)
41 lcd.print("Volt Amp Watt");
42 lcd.setCursor(0,1);
43 lcd.print("Volt_amp ");
44 lcd.clear(); // start with a blank screen
45 Serial.print("Volt Amp " );
46 Serial.println("volt_amp_watt.ino" );
47 delay(500);
48 }
49
50 void loop() {
51
52 //int val = analogRead(batteryPin); // read the value from the sensor
53 int val = analogRead(sensorPin3);
54 float volts = (val / resistorFactor) * referenceVolts ; // calculate the ratio
55 Serial.print("Volts : ");
56 //Serial.println(volts); // print the value in volts
57 Serial.print(volts); // print the value in volts
58
59 float average = 0;
60 for(int i = 0; i < 1000; i++) {
61 average = average + (.0264 * analogRead(A2) -13.51) / 1000;
62 delay(1);
63 }
64 Serial.print(" Amps : ");
65 Serial.println(average);
66
67 lcd.setCursor(0,0); // set cursor to column 0, row 0 (the first row)
68 lcd.print("Volts: "); // change this text to whatever you like. keep it clean.
69 //lcd.setCursor(0,1); // set cursor to column 0, row 1
70 lcd.print(volts);
71
72 // if you have a 4 row LCD, uncomment these lines to write to the bottom rows
73 // and change the lcd.begin() statement above.
74 lcd.setCursor(0,2); // set cursor to column 0, row 2
75 lcd.print("Amps: ");
76 //lcd.setCursor(0,3); // set cursor to column 0, row 3
77 lcd.print(average);
78
79 delay(500);
80 }
Para que nos calcule los vatios, el nuevo reto, es que necesitamos
contemplar una nueva variable como es el tiempo. Se han de realizar unos
cálculos que considero claves a la hora de comprender el código.
Fig. 13
El esquema anterior nos sirve para medir una tensión alterna de rango
hasta 30V, la tensión a mesurar atraviesa el puente rectificador y es filtrada
por el electrolítico de 220uf/63V, luego llega al divisor de tensión como se
muestra y éste nos presenta la tensión a mesurar. Las resistencias R1 y
R2 se han calculado para que entreguen la tensión más cercana a la real
(la Vin al rectificarse y filtrarse se multiplica por √2 = 1.4142, luego la
tensión de salida del divisor debe descontar este 1.4142 para que la lectura
sea cercana a la real, después, como seguridad se ha puesto diodo zener
de 5V.1 evitando así que se deteriore el micro.
UN MOMENTO.
Fig. 15
Sólo nos queda realizar el boceto que aúna los tres dispositivos en uno.
Veamos:
EL CÓDIGO.
En esta ocasión se interviene el tiempo para extraer los vatios/hora.
1 /*
2 watt_meter_lcd.ino
3 Este boceto se describe cómo conectar un Sensor de Corriente ACS715
4 (http://www.pololu.com/catalog/product/1186) a un Arduino,
5 y leer la corriente que fluye a través del sensor.
6
7 */
8 #include <LiquidCrystal.h> // lib. LiquidCrystal.h
9
10 //LCD: (RS, E,D4,D5,D6,D7)
11 LiquidCrystal lcd(8, 7, 6, 5, 4, 3); // mi config.
12 /*
13
14 Vcc a tarjeta sensora para Arduino + 5v
15 GND a tarjeta sensora para Arduino GND
16 OUT a tarjeta sensora para Arduino A0
17
18 Inserte las patillas de potencia en el circuito conductor positivo de carga,
19 la flecha en puntos del soporte board para cargar, otro enganche se conecta
20 al positivo de fuente alimentación.
21
22 Divisor de Voltage:
23
24 R1 = 47k a A2
25 R2 = 9400 a GND
26
27 Vin = 29,89V
28 Vout = 5V
29 Ratio 5,978
30
31 */
32 int batMonPin = A2; //A2 pin entrada del divisor voltage
33 int batVal = 0; // variable para el valor A/D
34 float pinVoltage = 0; // variable que contiene la tensión calculada
35 float batteryVoltage = 0;
36
37 int analogInPin = A1; //A0 pin de entrada mV está conectado a Salida sensor ASC712
38 int sensorValue = 0; // valor leído de la tarjeta soporte ASC712
39 int outputValue = 0; // salida en milliamps
40 unsigned long msec = 0;
41 float time = 0.0;
42 int sample = 0;
43 float totalCharge = 0.0;
44 float averageAmps = 0.0;
45 float ampSeconds = 0.0;
46 float ampHours = 0.0;
47 float wattHours = 0.0;
48 float amps = 0.0;
49
50 // Estos valores para max. Vin = 30V
51 // R1=4700Ω; R2=943Ω. para mayor impedancia
52 int R1 = 47000; // Resistencia of R1 in ohms
53 int R2 = 9400; // Resistencia of R2 in ohms
54
55 float ratio = 0; // Calculated from R1 / R2 = 4,984
56
57 void setup() {
58 // inicializa comunicaciones Serial a 9600 bps:
59 Serial.begin(9600);
60 lcd.begin(20, 4);
61 }
62
63 void loop() {
64
65 int sampleBVal = 0; // muestra V
66 int avgBVal = 0; // porcentage
67 int sampleAmpVal = 0; // muestra A
68 int avgSAV = 0; // porcentage
69
70 for (int x = 0; x < 10; x++){ // ejecutar a través del bucle de 10x
71
72 // leer el valor analógico en:
73 sensorValue = analogRead(analogInPin); //
74 sampleAmpVal = sampleAmpVal + sensorValue; // añadir muestras juntas
75
76 batVal = analogRead(batMonPin); // leer el voltaje en el divisor
77 sampleBVal = sampleBVal + batVal; // añadir muestras juntas
78
79 delay (10); // dejar resolver ADC antes de siguiente muestra
80 }
81
82 avgSAV = sampleAmpVal / 10; // saca el %
83
84 // convert to milli amps
85 outputValue = (((long)avgSAV * 5000 / 1024) - 500 ) * 1000 / 66; // según sensor 66 o 133 mA
86
87 /* sensor da salida sobre 100 en reposo.
88 Analog read produces a value of 0-1023, equiparando de 0v a 5v.
89 "((long)sensorValue * 5000 / 1024)"es la tensión en la salida del sensor en milivoltios.
90 Hay un desplazamiento a restar 500 mv.
91 La unidad produce 66 mV / 133 mV por amperio de corriente, por lo
92 que se divide por 0.066 / 0.133 para convertir mV a mA
93 */
94
95 avgBVal = sampleBVal / 10; //divide by 10 (number of samples) to get a steady reading
96
97 pinVoltage = avgBVal * 0.0048; // 0,00610 Calculate the voltage on the A/D pin
98 /* Una lectura de 1 para el A / D = 0.0048mV
99 Si multiplicamos la lectura A / D por 0,00488
100 entonces obtenemos el voltaje en el pin.
101
102 ¡NOTA! 0,00488 es ideal. Tuve que ajustar a 0,00610
103 contador para que coincida.
104
105 También, dependiendo de la tensión, del cableado y
106 donde se está leyendo, bajo voltaje fuertes cargas
107 que se muestra puede ser bien bajo voltaje en el
108 suministro. Supervisar la carga o la alimentación y decidir.
109 */
110
111 ratio = (float)R1 / (float)R2;
112 batteryVoltage = pinVoltage * ratio; // Utilice la relación calculada del divisor
113 // de tensión para calcular la tensión de la batería
114 amps = (float) outputValue / 1000;
115 float watts = amps * batteryVoltage;
116
117 Serial.print("Volts = " );
118 Serial.print(batteryVoltage);
119 // Serial.print("\t Current (amps) = ");
120 Serial.print(" Current (amps) = ");
121 Serial.print(amps);
122 // Serial.print("\t Power (Watts) = ");
123 Serial.print(" Power (Watts) = ");
124 Serial.print(watts);
125
126 sample = sample + 1;
127 msec = millis();
128
129 time = (float) msec / 1000.0;
130 totalCharge = totalCharge + amps;
131 averageAmps = totalCharge / sample;
132 ampSeconds = averageAmps*time;
133 ampHours = ampSeconds/3600;
134 wattHours = batteryVoltage * ampHours;
135
136 // Serial.print("\t Time (hours) = ");
137 Serial.print(" Time (hours) = ");
138 Serial.println(time/3600);
139
140 // Serial.print("\t Amp Hours (ah) = ");
141 // Serial.print(ampHours);
142 // Serial.print("\t Watt Hours (wh) = ");
143 // Serial.println(wattHours);
144
145 lcd.setCursor(0,0);
146 lcd.print(batteryVoltage);
147 lcd.print(" V ");
148 lcd.print(amps);
149 lcd.print(" A ");
150
151 lcd.setCursor(0,1);
152 lcd.print(watts);
153 lcd.print(" W ");
154 lcd.print(time/3600);
155 lcd.print(" H ");
156
157 lcd.setCursor(0,2);
158 lcd.print(ampHours);
159 lcd.print(" Ah ");
160 lcd.print(wattHours);
161 lcd.print(" Wh ");
162
163 lcd.setCursor(0,3);
164 lcd.print(ratio, 5);
165 lcd.print(" ");
166 lcd.print(avgBVal);
167
168 // wait 10 milliseconds before the next loop
169 // for the analog-to-digital converter to settle
170 // after the last reading:
171 delay(10);
172 }