How to make a DC Multimeter?-Your Magnifying Glass for Electricity⚡-Educational Multimeter
I invite you to build your first prototype multimeter or better yet to improve it, I want this project to evolve through your hands and ingenuity.
Components and supplies
1
Carbon Film Resistor 330KOhm
1
5 x 7 cm Perforated Grid Board
3
Metal film Resistor-1kohm-Tolerance 1%-1/4W
1
Module I2C For LCD 16X2
1
16x2 LCD display with I²C interface
1
Banana plug Female 4mm
1
Arduino Mega 2560 Rev3
1
Ceramic resistor 10w 1ohm
1
Double Side PCB board 3x7 CM
1
Carbon Film Resistor 1.5MOHM
3
Puss Buttons 12x12x7.3 with capsule.
Tools and machines
1
Digital Multimeter
1
Soldering kit
Apps and platforms
1
Arduino IDE
Project description
Code
VRI ADC
cpp
.
1#include <Wire.h> 2#include <LiquidCrystal_I2C.h> 3 4// Definición del LCD I2C: dirección 0x27 y LCD de 16x2u 5LiquidCrystal_I2C lcd(0x27, 16, 2); 6// Definición de pines 7const int pulsador1Pin = 30; // Pin del pulsador 1 (Amperímetro) 8const int pulsador2Pin = 33; // Pin del pulsador 2 (Ohmímetro) 9const int pulsador3Pin = 35; // Pin del pulsador 3 (Voltímetro) 10const int analogPin = A0; // Pin analógico para el voltímetro 11const int pinA14 = A14; // Pin A14 para un extremo de la resistencia shunt 12const int pinA7 = A7; // Pin A7 para el otro extremo de la resistencia shunt 13 14#define VI A3 // Referencia de voltaje 5 volts para el puente Wheatstone 15#define VA A1 // Lado A del puente 16#define VB A2 // Lado B del puente 17 18 19// Divisor de voltaje y variables 20const float R1 = 1527000.00; 21const float R2 = 329100.00;; 22const float v_ref = 5.00; 23const float resistor_ratio = R2 / (R1 + R2); 24float V = 0.00; 25 26// Shunt y variables de corriente 27const float shuntResistor = 1.0; // Resistencia shunt en ohmios 28int valoradc = 0.0; 29float voltage = 0.0; 30float current = 0.0; 31 32// Resistencia de referencia para el puente Wheatstone 33const float R = 990; 34 35// Estado de los pulsadores 36enum Pulsador { NONE, PULSADOR1, PULSADOR2, PULSADOR3 }; 37Pulsador pulsadorActivo = NONE; 38 39void setup() { 40 Serial.begin(9600); 41 lcd.init(); // Inicializar LCD I2C 42 lcd.backlight(); // Encender la luz de fondo del LCD 43 44 pinMode(pulsador1Pin, INPUT_PULLUP); 45 pinMode(pulsador2Pin, INPUT_PULLUP); 46 pinMode(pulsador3Pin, INPUT_PULLUP); 47} 48 49void loop() { 50 // Leer el estado de los pulsadores 51 int lecturaPulsador1 = digitalRead(pulsador1Pin); 52 int lecturaPulsador2 = digitalRead(pulsador2Pin); 53 int lecturaPulsador3 = digitalRead(pulsador3Pin); 54 55 // Detectar cambios de estado y realizar acciones 56 if (lecturaPulsador1 == LOW && pulsadorActivo != PULSADOR1) { 57 manejarPulsador(PULSADOR1); 58 } else if (lecturaPulsador2 == LOW && pulsadorActivo != PULSADOR2) { 59 manejarPulsador(PULSADOR2); 60 } else if (lecturaPulsador3 == LOW && pulsadorActivo != PULSADOR3) { 61 manejarPulsador(PULSADOR3); 62 } 63 64 // Ejecutar la medición según el modo activo 65 switch (pulsadorActivo) { 66 case PULSADOR1: 67 68 medirCorriente(); 69 break; 70 case PULSADOR2: 71 medirResistencia(); 72 73 break; 74 case PULSADOR3: 75 medirVoltaje(); 76 77 break; 78 default: 79 break; 80 } 81 82 delay(50); // Pequeño retraso para evitar rebotes en los pulsadores 83} 84 85void manejarPulsador(Pulsador pulsador) { 86 pulsadorActivo = pulsador; 87 lcd.clear(); 88 switch (pulsador) { 89 case PULSADOR1: 90 Serial.println("Modo: Amperímetro"); 91 lcd.print("Amperimetro"); 92 93 94 break; 95 case PULSADOR2: 96 Serial.println("Modo: Ohmímetro"); 97 lcd.print("Ohmetro"); 98 99 break; 100 case PULSADOR3: 101 Serial.println("Modo: Voltímetro"); 102 lcd.print("Voltimetro"); 103 104 105 106 break; 107 default: 108 break; 109 } 110} 111float lastVoltage = -1.0; 112void medirVoltaje() { 113 long valoradc = 0; 114 float voltajemedido = 0.00; 115 116 for (int i = 0; i < 100; i++) { 117 valoradc += analogRead(analogPin);//valor del 0 al 1023 118 delay(10); 119 } 120 valoradc /= 100; 121 voltajemedido = (valoradc * v_ref) / 1023.0; 122 V = voltajemedido / resistor_ratio; 123 124// escala 125// Escala automática con precisión variable 126String unit = " V"; 127float displayVoltage; 128 129// Ajuste de precisión según el valor de V 130if (V < 1.0) { 131 displayVoltage = V; // Mantener V como float 132} else { 133 displayVoltage = V; // Dejar en V 134} 135 136Serial.print("Voltaje: "); 137Serial.print(displayVoltage, (V < 1.0) ? 3 : 3); // 5 decimales si <1V, 3 si >=1V 138Serial.println(unit); 139Serial.println(analogRead(analogPin)); 140 141// Solo actualiza el LCD si el valor ha cambiado más de 0.026V 142if (abs(displayVoltage - lastVoltage) > 0.026) { 143 lcd.clear(); 144 lcd.print("Voltimetro"); 145 lcd.setCursor(0, 1); 146 lcd.print("V: "); 147 lcd.print(displayVoltage, (V < 1.0) ? 3 : 3); // Aplicar precisión en LCD 148 lcd.print(unit); 149 lastVoltage = displayVoltage; 150} 151} 152//CORRIENTE 153void medirCorriente() { 154 int valoradcA14 = 0; 155 int valoradcA7 = 0; 156 157 // Promediar 20 lecturas del ADC en ambos pines 158 for (int i = 0; i < 20; i++) { 159 valoradcA14 += analogRead(pinA14); 160 valoradcA7 += analogRead(pinA7); 161 delay(10); 162 } 163 164 valoradcA14 = valoradcA14 / 20; 165 valoradcA7 = valoradcA7 / 20; 166 167 // Convertir a voltaje en ambos pines 168 float voltageA14 = (valoradcA14 / 1023.0) * 5; 169 float voltageA7 = (valoradcA7 / 1023.0) * 5; 170 171 // Calcular la diferencia de voltaje a través de la resistencia shunt 172 float voltageDiff = voltageA7 - voltageA14; 173 174 // Calcular la corriente usando la resistencia shunt 175 current = voltageDiff / shuntResistor; 176 177 // Visualizar valores de ADC en el Serial Monitor 178 179 // Visualizar voltajes calculados 180 Serial.print("Voltaje A7: "); 181 Serial.print(voltageA7, 4); 182 Serial.print("Voltaje A14: "); 183 Serial.print(voltageA14, 4); // 6 decimales para mayor precisión 184 185 Serial.println("Corriente"); 186 Serial.println(current, 4); 187 188 189 Serial.print("Voltaje ADC7: "); 190 Serial.println(valoradcA7); 191 Serial.print("Voltaje ADC14: "); 192 Serial.println(valoradcA14); 193 // Visualizar la diferencia de voltaje 194 195 // Autoescala 196 String unit = "A"; 197 float displayCurrent= current ; 198 199 200 Serial.print("Corriente: "); 201 Serial.print(displayCurrent, 3); 202 Serial.println(unit); 203 204 lcd.setCursor(0, 1); // Segunda línea de la pantalla LCD 205 lcd.print("I: "); 206 lcd.print(displayCurrent, 3); 207 lcd.print(unit); 208} 209 210 211 212//RESISTENCIA 213// DEFINO LA Función para promediar lecturas del ADC.Para luego usarla mas adelante 214float averageADC(int pin) { 215 long total = 0; // Usar long para evitar desbordamiento 216 for (int i = 0; i < 20; i++) { 217 int lectura = analogRead(pin);//valor adc 218 total += analogRead(pin); 219 delay(10); // Pequeña pausa para estabilizar la lectura 220 } 221 return total /20; // Promedio 222} 223float getResistanceValue(float viADC, float vaADC, float vbADC) { 224 225 // Aplicar corrección solo a vbADC si es mayor a 1010 226 //if (vbADC > 1005) { 227 // vbADC -= 2; // Aplica la corrección que consideres necesaria vBADC=vbADC-3 si vBADC=1005 228 //} 229 230 // Convertir los valores del ADC a voltaje 231 float vi = (viADC / 1023.0) * v_ref; 232 float va = (vaADC / 1023.0) * v_ref; 233 float vb = (vbADC / 1023.0) * v_ref; 234 235 float resistance = R * (vi - 2.0 * (va - vb)) / (vi + 2.0 * (va - vb)); // Fórmula corregida para el puente de Wheatstone 236 237 return resistance; 238} 239 240 241 242// Verifica si los voltajes en los nodos del puente son razonables 243bool puenteWheatstoneValido(float vi, float va, float vb) { 244 return (vi > 0.01 && va > 0.01 && vb > -0.0000001 && va < vi && vb < vi); 245} 246 247void medirResistencia() { 248 float viADC = averageADC(VI); // Promediar la lectura de VI 249 float vaADC = averageADC(VA); // Promediar la lectura de VA 250 float vbADC = averageADC(VB); // Promediar la lectura de VB 251 252 253 // Serial para ver los valores promedio 254 Serial.print("VI (ADC): "); 255 Serial.print(viADC); 256 Serial.print(" VA (ADC): "); 257 Serial.print(vaADC); 258 Serial.print(" VB (ADC): "); 259 Serial.println(vbADC); 260 261 262 if (!puenteWheatstoneValido(viADC, vaADC, vbADC)) { 263 lcd.setCursor(0, 1); 264 lcd.print("R: OL "); 265 Serial.println("Resistencia: OL"); 266 delay(1000); 267 return; 268 } 269 270 float resistance = getResistanceValue(viADC, vaADC, vbADC); 271 displayValue(resistance); 272 delay(1000); 273} 274 275void displayValue(float r) { 276 lcd.setCursor(0, 1); // Segunda línea de la pantalla LCD 277 278 // Autoescala 279 String unit; 280 float displayResistance; 281 if (r >= 50000.0) { 282 displayResistance = r / 1000.0; // Convertir a kOhm 283 unit = " kOhm"; 284 } else { 285 displayResistance = r; // Dejar en Ohm 286 unit = " Ohm"; 287 } 288 289 lcd.print("R: "); 290 lcd.print(displayResistance, 3); 291 lcd.print(unit); 292 293 Serial.print("Resistencia: "); 294 Serial.print(displayResistance, 3); 295 Serial.println(unit); 296}
Downloadable files
Variable Resolution Ohmmeter
Measurement values
Ohmetro1-Resolucion.pdf
Comments
Only logged in users can leave comments