Introducción.
Esta es otra forma de utilizar nuestro Arduino para mesurar tensiones y corrientes continuas, ya se ha descrito en estas páginas un voltímetro, un sensor de corriente, sin embargo en esta ocasión veremos una forma sencilla de realizar este tipo de medidor para nuestro uso o incluso para aplicar en proyectos industriales si es el caso.
Circuito de entrada.
El circuito de entrada de datos o tomas de mesura, es bastante sencillo y tiene la particularidad de utilizar resistencias de precisión de valores bastante comunes como veremos a continuación.
Como puede apreciarse por un lado tenemos dos entradas de la tensión que queremos conocer, una es GND que es normalmente la masa común, la otra entrada corresponde al positivo y será aplicada al terminal +VCC. Además, utilizaremos una resistencia de 95KΩ y una resistencia de 10.600Ω para conformar el divisor de tensión que nos permitirá medir una tensión máxima de 30V, el punto medio del divisor lo aplicaremos al pin A0 del Arduino para leer los voltios.
En segundo lugar tenemos una borna (+ =>) y otra borna (<=-) entre ambas debemos conectar la carga que corresponda, para medir la corriente de paso, como se aprecia en el esquema la salida se aplicará al pin A1.
Observar que en esta imagen se han ‘cortado’ ciertas conexiones que sólo representan los elementos que deben ser sustituidos por los reales, en el momento de hacer las medidas. La tensión del circuito que vamos a medir se aplica entre +Vss y GND.
Para medir una corriente, normalmente qué hacemos, cortamos el cable y conectamos el amperímetro en serie, exactamente eso es lo que haremos con este montaje. Por ese motivo he cortado la carga y los terminales sólo representan donde irá conectada la carga.
Fig. 3
Si necesita una ayuda para el cálculo de las resistencias del divisor, puede servirse de estos descriptivos enlaces: calculograficoresitivo y divisor de tensión.
El Voltímetro.
El siguiente código corresponde a un Voltímetro que nos mide los voltios en el pin A0.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
/* dcvoltmeter.ino Un DVM basado en el concepto divisor voltaje con Arduino de T.K.Hareendran Voltímetro Digital 0V to 55V con Arduino Aquí un circuito útil para los amantes y los experimentadores Arduino. Es un simple voltímetro digital, que puede medir con seguridad voltajes de corriente continua de entrada en el rango de 0 a 30V. La placa Arduino puede ser alimentada por una batería estándar de 9V, como de costumbre. Como usted bien sabe, las entradas analógicas de Arduino se puede utilizar para medir el voltaje DC entre 0 y 5V (cuando se utiliza la tensión de referencia analógica estándar 5V) y este rango se puede aumentar mediante el uso de dos resistencias para crear un divisor de tensión. El divisor de tensión disminuye la tensión medida a estar dentro del rango de las entradas analógicas de Arduino. Código en el boceto Arduino se utiliza entonces para calcular la tensión real que se está midiendo. El sensor analógico de la placa Arduino detecta el voltaje en el pin analógico y lo convierte en un formato digital que puede ser procesado por el micro- controlador. Aquí, estamos alimentando la tensión de entrada al pin analógico (A0) utilizando un circuito divisor de tensión que comprende las resistencias R1 sencilla (100K) y R2 (10K). Con los valores utilizados en el divisor de tensión es posible alimentar la tensión de 0V a 55V en la placa Arduino. La unión en la red de divisor de tensión conectado al pin el análogo Arduino es equivalente a la tensión de entrada dividido por 11, por lo que 55V ÷ 11 = 5V. En otras palabras, cuando se miden 55V, el pin analógico Arduino estará en su máximo voltaje de 5V. Así, en la práctica, es mejor para etiquetar este voltímetro como "0-30V DVM" para añadir un margen de seguridad! Si la lectura de la pantalla no coincide cuando se comparan con su DVM laboratorio, utilice un multímetro digital de precisión para encontrar la resistencia real de R1 y R2, y reemplazar R1 = 100000 y R2 = 10000 en el código con el que los valores. Seguidamente compruebe la alimentación de 5V con el DVM laboratorio en los pines GND y 5V de la placa Arduino. Podría darle menos (por ejemplo 4.95V), sustituya el valor en el código vout = (valor * 5.0) / 1024.0 (es decir, sustituir el 5.0 a la lectura V real, en este caso 4.95V). Para ambientes industriales, conviene poner un condensador de 100nf en paralelo a la entrada del pin analógico, en este caso pin A0. Además, el valor de R1 y R2 se han reducido, por el mismo motivo (lea el artículo). Trate siempre de usar las resistencias de precisión de tolerancia del 1% para R1 y R2. Los valores de resistencia (R1 y R2) en el diagrama del circuito proporcionan cierta protección contra sobretensiones al medir voltajes bajos. Mantenga en mente que cualquier tensión de entrada superior a aproximadamente 55V podría freír el Arduino. Ningún otro tipo de protección (por picos de tensión, tensiones inversas o voltajes más altos) se incorpora en este circuito! funciona bien 05.08.2016 */ #include <LiquidCrystal.h> // lib. LiquidCrystal.h // LCD:..........RS,E,D4,D5,D6,D7) LiquidCrystal lcd(8,7, 6, 5, 4, 3); // int analogInput = A0; float vout = 0.0; float vin = 0.0; float R1 = 100000;// resistance of R1 (47000) -see text! float R2 = 10000; // resistance of R2 (9400) - see text! int value, val = 0; void setup(){ Serial.begin (9600); Serial.println("DCVoltmeter"); Serial.println("DCVoltmeter.ino"); Serial.println("05.08.2016"); pinMode(analogInput, INPUT); lcd.begin(20, 4); lcd.setCursor(0,0); lcd.print("DC VOLTMETER"); lcd.setCursor(0,1); lcd.println("DCVoltmeter.ino"); lcd.setCursor(0,2); lcd.println("30.08.2016"); delay(1500); lcd.clear(); } void loop(){ float sampleBVal = 0; // read the value at analog input for (int x = 0; x < 500; x++){ val = analogRead(analogInput); sampleBVal = sampleBVal + val; } float value = sampleBVal/500; float vout = ((value * 5.0)+ 12) / 1024.0; // see text // el +12 es un valor ajustado para compensar los valores restantes float vin = vout / (R2/(R1+R2)); Serial.print("Volts= "); Serial.println(vin); lcd.setCursor(0,0); lcd.print("DC VOLTMETER"); lcd.setCursor(0, 1); lcd.print("OUTPUT V= "); lcd.setCursor(10, 1); lcd.print(vin, 2); lcd.print(" "); delay(500); } |
En el anterior código se logra una lectura estable de tensión, lo cual nos indica que vamos por el buen camino. En el próximo código intentaremos añadir la opción de leer la corriente siguiendo las posibilidades del esquema de la anterior figura 2.
Parámetros del voltímetro.
Estos son los valores obtenidos de las medidas tomadas.
Tabla valores.
El amperímetro.
El siguiente código que ya vimos en sensor de corriente, con el que medir la corriente de paso de un circuito mediante el sensor ACS712 de carga.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
/* watt_meter_lcd.ino Este boceto se describe cómo conectar un Sensor de Corriente ACS715 (http://www.pololu.com/catalog/product/1186) a un Arduino, y leer la corriente que fluye a través del sensor. */ #include <LiquidCrystal.h> // lib. LiquidCrystal.h //LCD: (RS, E,D4,D5,D6,D7) LiquidCrystal lcd(8, 7, 6, 5, 4, 3); // mi config. /* Vcc a tarjeta sensora para Arduino + 5v GND a tarjeta sensora para Arduino GND OUT a tarjeta sensora para Arduino A0 Inserte las patillas de potencia en el circuito conductor positivo de carga, la flecha en puntos del soporte board para cargar, otro enganche se conecta al positivo de fuente alimentación. Divisor de Voltage: R1 = 47k a A2 R2 = 9400 a GND Vin = 29,89V Vout = 5V Ratio 5,978 */ int batMonPin = A2; //A2 pin entrada del divisor voltage int batVal = 0; // variable para el valor A/D float pinVoltage = 0; // variable que contiene la tensión calculada float batteryVoltage = 0; int analogInPin = A1; //A0 pin de entrada mV está conectado a Salida sensor ASC712 int sensorValue = 0; // valor leído de la tarjeta soporte ASC712 int outputValue = 0; // salida en milliamps unsigned long msec = 0; float time = 0.0; int sample = 0; float totalCharge = 0.0; float averageAmps = 0.0; float ampSeconds = 0.0; float ampHours = 0.0; float wattHours = 0.0; float amps = 0.0; // Estos valores para max. Vin = 30V // R1=4700Ω; R2=943Ω. para mayor impedancia int R1 = 47000; // Resistencia of R1 in ohms int R2 = 9400; // Resistencia of R2 in ohms float ratio = 0; // Calculated from R1 / R2 = 4,984 void setup() { // inicializa comunicaciones Serial a 9600 bps: Serial.begin(9600); lcd.begin(20, 4); } void loop() { int sampleBVal = 0; // muestra V int avgBVal = 0; // porcentage int sampleAmpVal = 0; // muestra A int avgSAV = 0; // porcentage for (int x = 0; x < 10; x++){ // ejecutar a través del bucle de 10x // leer el valor analógico en: sensorValue = analogRead(analogInPin); // sampleAmpVal = sampleAmpVal + sensorValue; // añadir muestras juntas batVal = analogRead(batMonPin); // leer el voltaje en el divisor sampleBVal = sampleBVal + batVal; // añadir muestras juntas delay (10); // dejar resolver ADC antes de siguiente muestra } avgSAV = sampleAmpVal / 10; // saca el % // convert to milli amps outputValue = (((long)avgSAV * 5000/ 1024) - 500) * 1000/ 66; //según sensor 66 o 133 mA /* sensor da salida sobre 100 en reposo. Analog read produces a value of 0-1023, equiparando de 0v a 5v. "((long)sensorValue * 5000 / 1024)"es la tensión en la salida del sensor en milivoltios. Hay un desplazamiento a restar 500 mv. La unidad produce 66 mV / 133 mV por amperio de corriente, por lo que se divide por 0.066 / 0.133 para convertir mV a mA */ avgBVal = sampleBVal / 10; //divide by 10 (number of samples) to get a steady reading pinVoltage = avgBVal * 0.00488; // 0,00610 Calculate the voltage on the A/D pin /* Una lectura de 1 para el A / D = 0.00488mV Si multiplicamos la lectura A / D por 0,00488 entonces obtenemos el voltaje en el pin. ¡NOTA! 0,00488 es ideal. Tuve que ajustar contador a 0,00610 para que coincida. También, dependiendo de la tensión, del cableado y donde se está leyendo, bajo voltaje, fuertes cargas que se muestra puede ser bien bajo voltaje en el suministro. Supervisar la carga o la alimentación y decidir. */ ratio = (float)R1 / (float)R2; batteryVoltage = pinVoltage * ratio; // Utilice la relación calculada del divisor // de tensión para calcular la tensión de la batería amps = (float) outputValue / 1000; float watts = amps * batteryVoltage; Serial.print("Volts = " ); Serial.print(batteryVoltage); // Serial.print("\t Current (amps) = "); Serial.print(" Current (amps) = "); Serial.print(amps); // Serial.print("\t Power (Watts) = "); Serial.print(" Power (Watts) = "); Serial.print(watts); sample = sample + 1; msec = millis(); time = (float) msec / 1000.0; totalCharge = totalCharge + amps; averageAmps = totalCharge / sample; ampSeconds = averageAmps*time; ampHours = ampSeconds/3600; wattHours = batteryVoltage * ampHours; // Serial.print("\t Time (hours) = "); Serial.print(" Time (hours) = "); Serial.println(time/3600); // Serial.print("\t Amp Hours (ah) = "); // Serial.print(ampHours); // Serial.print("\t Watt Hours (wh) = "); // Serial.println(wattHours); lcd.setCursor(0,0); lcd.print(batteryVoltage); lcd.print(" V "); lcd.print(amps); lcd.print(" A "); lcd.setCursor(0,1); lcd.print(watts); lcd.print(" W "); lcd.print(time/3600); lcd.print(" H "); lcd.setCursor(0,2); lcd.print(ampHours); lcd.print(" Ah "); lcd.print(wattHours); lcd.print(" Wh "); lcd.setCursor(0,3); lcd.print(ratio, 5); lcd.print(" "); lcd.print(avgBVal); // wait 10 milliseconds before the next loop // for the analog-to-digital converter to settle // after the last reading: delay(10); } |
Este código nos sirve para implementar con el código que necesitamos.
Volt-amperímetro.
El siguiente código es el compendio de los anteriores con el que podremos medir los distintos valores de tensión y corriente, y mediante las oportunas operaciones obtendremos los vatios.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
/* watimetro_lcd.ino This sketch describes how to connect a ACS715 Current Sense Carrier (http://www.pololu.com/catalog/product/1186) to the Arduino, and read current flowing through the sensor. */ #include <LiquidCrystal.h> // #include LiquidCrystal.h // LiquidCrystal lcd(7, 8, 9, 10, 11, 12); //LCD:...........(RS, E,D4,D5,D6,D7) LiquidCrystal lcd(8, 7, 6, 5, 4, 3); // mi config. /* Vcc on carrier board to Arduino +5v GND on carrier board to Arduino GND OUT on carrier board to Arduino A0 Insert the power lugs into the loads positive lead circuit, arrow on carrier board points to load, other lug connects to power supply positive Voltage Divider 11.66 from + to A4 4.62k from A4 to Gnd Ratio 2.5238 */ int batMonPin = A4; // input pin for the voltage divider int batVal = 0; // variable for the A/D value float pinVoltage = 0; // variable to hold the calculated voltage float batteryVoltage = 0; int analogInPin = A0; // Analog input pin that the carrier board OUT is connected to int sensorValue = 0; // value read from the carrier board int outputValue = 0; // output in milliamps unsigned long msec = 0; float time = 0.0; int sample = 0; float totalCharge = 0.0; float averageAmps = 0.0; float ampSeconds = 0.0; float ampHours = 0.0; float wattHours = 0.0; float amps = 0.0; int R1 = 11660; // Resistance of R1 in ohms int R2 = 4620; // Resistance of R2 in ohms float ratio = 0; // Calculated from R1 / R2 void setup() { // initialize serial communications at 9600 bps: Serial.begin(9600); lcd.begin(20, 4); lcd.println(" watt_meter_lcd2.ino "); delay(500); lcd.clear(); } void loop() { int sampleBVal = 0; int avgBVal = 0; int sampleAmpVal = 0; int avgSAV = 0; for (int x = 0; x < 50; x++){ // run through loop 10x // read the analog in value: sensorValue = analogRead(analogInPin); sampleAmpVal = sampleAmpVal + sensorValue; // add samples together batVal = analogRead(batMonPin); // read the voltage on the divider sampleBVal = sampleBVal + batVal; // add samples together delay (10); // let ADC settle before next sample } avgSAV = sampleAmpVal / 50; // convert to milli amps outputValue = (((long)avgSAV * 5000 / 1024) - 500 ) * 1000 / 66; // 133 /* sensor outputs about 100 at rest. Analog read produces a value of 0-1023, equating to 0v to 5v. "((long)sensorValue * 5000 / 1024)" is the voltage on the sensor's output in millivolts. There's a 500mv offset to subtract. The unit produces 133mv per amp of current, so divide by 0.133 to convert mv to ma */ avgBVal = sampleBVal / 50; //divide by 10 (number of samples) to get a steady reading pinVoltage = avgBVal * 0.00610; // Calculate the voltage on the A/D pin /* A reading of 1 for the A/D = 0.0048mV if we multiply the A/D reading by 0.00488 then we get the voltage on the pin. NOTE! .00488 is ideal. I had to adjust to .00610 to match fluke meter. Also, depending on wiring and where voltage is being read, under heavy loads voltage displayed can be well under voltage at supply. monitor at load or supply and decide. */ ratio = (float)R1 / (float)R2; batteryVoltage = pinVoltage * ratio; // Use the ratio calculated for the voltage divider // to calculate the battery voltage amps = (float) outputValue / 1000; float watts = amps * batteryVoltage; Serial.print("Volts = " ); Serial.print(batteryVoltage); Serial.print("\t Current (amps) = "); Serial.print(amps); Serial.print("\t Power (Watts) = "); Serial.print(watts); sample = sample + 1; msec = millis(); time = (float) msec / 1000.0; totalCharge = totalCharge + amps; averageAmps = totalCharge / sample; ampSeconds = averageAmps*time; ampHours = ampSeconds/3600; wattHours = batteryVoltage * ampHours; Serial.print("\t Time (hours) = "); Serial.print(time/3600); Serial.print("\t Amp Hours (ah) = "); Serial.print(ampHours); Serial.print("\t Watt Hours (wh) = "); Serial.println(wattHours); lcd.setCursor(0,0); lcd.print(batteryVoltage); lcd.print(" V "); lcd.print(amps); lcd.print(" A "); lcd.setCursor(0,1); lcd.print(watts); lcd.print(" W "); lcd.print(time/3600); lcd.print(" H "); lcd.setCursor(0,2); lcd.print(ampHours); lcd.print(" Ah "); lcd.print(wattHours); lcd.print(" Wh "); lcd.setCursor(0,3); lcd.print(ratio, 5); lcd.print(" "); lcd.print(avgBVal); // wait 10 milliseconds before the next loop // for the analog-to-digital converter to settle // after the last reading: delay(10); } |
Desde mi experiencia, hay un aspecto que debo aclarar; puesto que la tensión de trabajo de nuestro Arduino no siempre es de 5V, hay que corregir la formula, debemos medir con nuestro mejor voltímetro dicha tensión, que será la tensión de referencia, eso dará una precisión mayor a nuestro voltímetro. Algunos han incluido valores aleatorios ajustándolos para mejorar la lectura.
He tratado de utilizar valores razonados, de modo que, he modificado la formula que quedará así:
vout = ((valor * 5.0)/0.0488)/1024.
Si usted que lee esto, pruebe esta formula y si considera que estoy en un error, por favor, muéstreme el motivo.