Desarrollando un multímetro digital con ICL7135 & PIC16F877A

Ratmayor

ModeraTroll
Como indica el título, estoy desarrollando un mutímetro benchtop digital usando como ADC un ICL7135 por su practicidad y usando un PIC16F877A a causa de que tengo tiempo libre, me sobran los componentes y no soy millonario como para comprar un multímetro benchtop ya armado como estos:
images.jpg
La idea de usar el PIC es primeramente para reducir componentes y porque con un display LCD se vería super cool :V y así está quedando la etapa de conversión:
adc.png
Ahora bien, para hacerlo compatible, estoy leyendo número por número del ICL7135 de esta manera:
C:
//Leer los datos del ADC externo
      if(input(D5)){ //Leer digito
         if(input(B1)){a=1;}else{a=0;} //Leer valor binario
         if(input(B2)){b=2;}else{b=0;}
         if(input(B3)){c=4;}else{c=0;}
         if(input(B4)){d=8;}else{d=0;}
         digit[4] = a+b+c+d; //Convertir binario a decimal
      }
      if(input(D4)){
         if(input(B1)){a=1;}else{a=0;}
         if(input(B2)){b=2;}else{b=0;}
         if(input(B3)){c=4;}else{c=0;}
         if(input(B4)){d=8;}else{d=0;}
         digit[3] = a+b+c+d;
      }
      if(input(D3)){
         if(input(B1)){a=1;}else{a=0;}
         if(input(B2)){b=2;}else{b=0;}
         if(input(B3)){c=4;}else{c=0;}
         if(input(B4)){d=8;}else{d=0;}
         digit[2] = a+b+c+d;
      }
      if(input(D2)){
         if(input(B1)){a=1;}else{a=0;}
         if(input(B2)){b=2;}else{b=0;}
         if(input(B3)){c=4;}else{c=0;}
         if(input(B4)){d=8;}else{d=0;}
         digit[1] = a+b+c+d;
      }
      if(input(D1)){
         if(input(B1)){a=1;}else{a=0;}
         if(input(B2)){b=2;}else{b=0;}
         if(input(B3)){c=4;}else{c=0;}
         if(input(B4)){d=8;}else{d=0;}
         digit[0] = a+b+c+d;
      }
El detalle con esto es que uno todo los dígitos en una sola cifra usando trucos en el printf
C:
dm = digit[4]*10000;
ml = digit[3]*1000;
ce = (digit[2]*1000)/10; //Esto es debido a un extraño bug en CCS que no permite multiplicar por 100
dc = digit[1]*10;
un = digit[0];
total = (dm+ml+ce+dc+un);
lcd_gotoxy(1,2);
printf(lcd_putc,"%lu     ",total);

Hasta ahí todo lindo, PERO, me gustaría saber si se les ocurre una mejor forma de leer el ADC y alguna forma de agregar los decimales necesarios para cambiar la escala, manteniendo una sola cifra, obvio podría hacer trampas con el prinft, PERO, no podría usar la cifra total para agregar operaciones matemáticas como en los benchtop, cualquier idea es bienvenida, ya que el proyecto es el de diseñar un multímetro Open Source con prestaciones de multímetro caro :V
 
Última edición:

capitanp

Miembro irreconocible
Ya que metiste un microcontrolador de por medio fijatate el Ads1115 tenes 4 entradas en modo común y 2 en modo diferencial y una mejor resolución que el 7135
 

Ratmayor

ModeraTroll
Ya que metiste un microcontrolador de por medio fijatate el Ads1115 tenes 4 entradas en modo común y 2 en modo diferencial y una mejor resolución que el 7135
Sí es mejor, pero es un poco inaccesible para los simples mortales... :V Aparte que esas interfaces seriales me parecen brujería / cosa del diablo :V
 

capitanp

Miembro irreconocible
Encontre esto por ahi..

Captura de pantalla 2020-09-07 a la(s) 12.09.22.png



Código:
#include <16f877a.h>
#fuses XT,NOWDT

#use delay(clock=4000000)
#include <lcd.c>

#use i2c(Master,sda=PIN_B2,scl=PIN_B4,FORCE_SW)

void main(){

   int1 flag0;
   int1 flag1;
   int1 flag2;
   int1 flag3;
   int1 flag4;
   int1 flag5;
   int1 flag6;
  
   int msb;
   int lsb;
  
   lcd_init();
   delay_ms(50);
  
   printf(lcd_putc,"\fInicio...");
   delay_ms(1000);
  
   while(1){

      //after a writing, flags go to 0 if master received ACK from slave
      flag0=1;
      flag1=1;
      flag2=1;
      flag3=1;
      flag4=1;
      flag5=1;
      flag6=1;
    
      //-------------------------configuration--------------------------------//
      i2c_start();
      flag0=i2c_write(0b10010000); // address = 0x90 | 0 -> write
      flag1=i2c_write(0b00000001); // 0x01 -> config register
      flag2=i2c_write(0b11000001); // 1 -> os, 100 -> an0-gnd, 000 -> +-6.144 range, 0/1 -> continuous/single conversion
      flag3=i2c_write(0b10000011); // default
      i2c_stop();
      //----------------------------reading-----------------------------------//
      i2c_start();
      flag4=i2c_write(0b10010000); // address = 0x90 | 0 -> write
      flag5=i2c_write(0b00000000); // 0x00/0x01 -> conversion/config register
      i2c_stop();     
      delay_ms(500);
      i2c_start();
      flag6=i2c_write(0b10010001); // address = 0x90 | 1 -> read
      msb = i2c_read();
      lsb = i2c_read(0); // No ACK from master
      i2c_stop();
      //----------------------------output------------------------------------//
      printf(lcd_putc,"\f%u %u %u\n%u %u %u %u",flag0,flag1,flag2,flag3,flag4,flag5,flag6); //makes sure the whole COM process was fine
      delay_ms(1000);
      printf(lcd_putc,"\fmsb,lsb=%u,%u",msb,lsb); //msb and lsb from conversion displays on lcd 16x2
      delay_ms(1000);
    
   }
}
 

Ratmayor

ModeraTroll
Estuve leyendo el post original de esa publicación, y el autor dice que no funciona... Aparte de que no pude conseguir las librerías del ADS1115 :(
 
Última edición:

Estuve analizando el código y técnicamente pasaría lo mismo que con el ICL7135, devuelve un número entero al que no se como agregarle los decimales ni cambiarle la escala :V


En cierto tiempo quería hacer uno igual a que estas haciendo pero termine haciendo otro proyecto :facepalm:, mas sin embargo era uno Coreano o Japones te adjunto el archivo a lo mejor te sea algo de utilidad.

1599502832967.png


1599502844792.png
 

Adjuntos

  • Multimetro Digital.rar
    24.4 KB · Visitas: 12
Última edición:

Ratmayor

ModeraTroll
Se me paso el Time de editar 🥺 el que hice hace muchos años fue un cloncito Fluke, me sirvió un buen tiempo pero ya no existe, usa el viejo y conocido 8051:

Excelente información!! Y ya resolví lo de los decimales, era aritmética simple, pero se me había recalentado el cerebro y la mononeurona no estaba operando bien :ROFLMAO::ROFLMAO:

Veo que en el proyecto que compartiste usaban reles para el selector de escala... Tenía la curiosidad sobre si usar relés o alguna opción de estado sólido como un CD4053 o similares... :unsure:
 

Ratmayor

ModeraTroll
El tema es el rango de tension/frecuencia (en caso de frecuencimetro) en el caso de los integrados. Si podes con rele, lo veo mas saludable
Lo consideré y como convertir frecuencia a tensión pudiera llegar a ser un desastre, pensé en medir la frecuencia inhabilitando el ADC y que el micro se encargue solito...

Otro detalle más a ver si alguien me da una mano, como usaré un display 16X2 tenía pensado usar el renglón de abajo como una barra... Intenté hacerla con CGRAM, pero me volví un desastre

C:
void bar(int lvl){
   int a,b;
   int address[7]={0x40,0x48,0x50,0x58,0x60,0x68,0x70}; //Aquí asigno los espacios en memoria de la LCD que voy a escribir
   int bytes[3]={0x10,0x14,0x15}; //Estas son las barras, 3 por caracter para que se vean uniformes
   for(b=0;b<3;b++){ //Aquí genero las 3 barras
      lcd_send_byte(0,address[1]); //Indico que grabar y en donde
      for(a=0;a<8;a++){
         lcd_send_byte(1,bytes[b]); //Grabamos la data de 8 bits en la LCD
      }
   }
   lcd_gotoxy(1,2); //Indicamos la posición
   lcd_send_byte(1,1); //Mostramos las barritas en la LCD
}

El problema con este código es que no supe como aplicarlo al valor total que está entregando el ADC, considerando que hay 48 barritas en total en toda la LCD...
 
Última edición:
Excelente información!! Y ya resolví lo de los decimales, era aritmética simple, pero se me había recalentado el cerebro y la mononeurona no estaba operando bien :ROFLMAO::ROFLMAO:

Veo que en el proyecto que compartiste usaban reles para el selector de escala... Tenía la curiosidad sobre si usar relés o alguna opción de estado sólido como un CD4053 o similares... :unsure:

Si y es lo ideal usar los Relés incluso el original los usa, el prototipo esta en una web de Corea, pero el diseño creo que es Japones :unsure:

1599519926971.png


 
Última edición:

Ratmayor

ModeraTroll
Hola Amigo, usar los caracteres personalizados de los LCD inteligentes no es tan complejo cómo parece. Por otro lado, cómo y qué formato te entrega el ADC que estás usando?
Entrega formado BCD ya que originalmente está concebido para trabajar con el 7447 y por otro lado entrega una señal secuencial para multiplexar los displays 7-seg.

Acá te dejo el enlace del Datasheet: https://datasheets.maximintegrated.com/en/ds/ICL7135.pdf mirando un poco, creo que si uso solo el pin de conteo D1 y el pin STROBE, podría ahorrarme unos cuantos pines y líneas de código... :unsure:
 
Última edición:

Ratmayor

ModeraTroll
Ojo, voy a usar reles, pero por alguna razón, en el Proteus hacen cosas muy raras, así que comencé a usar un 4051 como se aprecia en la imagen...
scala.png
Pero, por alguna extraña razón, al cambiar la escala, aparece un ruido infernal que no logro ubicar el porque, lo que hace aparecer otro problema. Estoy usando este código para auto detectar el rango:

C:
if(input(OVR)){ //Lee el pin over range y aumenta una escala
    if(scale < 4){ //Si llega al tope de la escala, detiene el conteo
        scale = scale + 1;
        delay_ms(100); //Se deja un delay para esperar a que el IC apague el pin Over range
    }
}
else if(input(UNR)){ //Lee el pin under range y baja una escala
    if(scale != 0){ //Si llega al tope de la escala detiene el conteo
        scale = scale - 1;
        delay_ms(100); //Se deja un delay para esperar a que el IC apague el pin Under range
    }
}
Hasta aquí todo bien, pero, a causa del ruido, el contador llega hasta el tope y estando en el tope vuelve a bajar 🤦‍♂️ será algo que estoy haciendo mal o es solo el simulador haciéndome bullying?
 
Arriba