Voltímetro con el ADC del PIC

Estado
Cerrado para nuevas respuestas.
#61
claro eso ya lo se pero el punto es como quiero un ejemplo de como hacer lo no soy tan pro de la programa
cion en c lo que se de pic es gracias a lo que busco por internet y a este foro por eso les pido ayuda a ustedes manes la hice la placa del voltimetro y lo voy a colgar pronto para que ven y comenten si hay algo por mejorar



aqui les pongo el pcb y el esquematico ayudenme a mejorar este proyecto las primeras pruebas las hice en el protoboard con cables muy largos ya de hecho hay una gran oscilacion no he problado aun en un placa con los componentes ya soldados
pero antes de llevarme una gran desilucion quiero tomar todas las precausiones
 

Adjuntos

Última edición:
#62
Hola a todos, buenas noches. Estaba leyendo el tema y me parece interesante, por lo que he querido compartir con ustedes y quien lo nececite un diseño mio. La fuente no es el proyecto ya que fue hecha para probar y luego la terminaré. Lo que me ocupé es de que presente tensión, corriente y potencia, además de limitar en tensión y corriente programable cuyo rebasamiento produce un corte momentaneo de la alimentación tras lo cual chequea el estado y de no cesar el problema mantiene el corte, caso contrario habilita nuevamente. Las indicaciones de como opera están en el Isis. No aporto la fuente porque está hecha con Niple, pero si a alguien le iteresa el asm o el npl lo subo. Saludo y gracias por aquellos comentarios que puedan aportar para su mejor realización.
 

Adjuntos

#63
Un promedio de mediciones en pseudocódigo seria algo así:

Código:
Inicio
Declarar variable 'i' como entero sin signo 8 bits
Declarar variable 'promedio' como entero sin signo 16 bits
Declarar variable 'resultado' como entero sin signo 16 bits
i = 0
promedio = 0
Mientras i sea menor a 20
{
 promedio = promedio + (Medición del ADC)
 i = i + 1
}

resultado = promedio / 20

Mostrar resultado
Por supuesto que este fragmento de código es para que lo implementes en tu programa, utilizando la sintaxis de tu compilador y los registros de tu micro.
 
#64
Lo ideal es usar un promedio móvil usando un vector que almacene las últimas "N" muestras.

Entonces, del código que publicó 2cool2you, si yo lo tuviera que hacer en "C", eso podría ser una función que por argumentos reciba la dirección del vector y la dirección de la variable donde se almacenará el resultado.
 
#69
pero esta en la carpeta del mensaje numero 61 ahi esta el esquematico y el pcb en aguila version 6.3.0 bueno pero igual voy a subir un nuevo mensaje donde pondre las parte principales
 
#72
No alcanzo a ver los valores de los componentes ni del PIC como tampoco la alimentación que le das a los operacionales (creo ver un +/- 15v), pero de lo que ví destaco esto:

Esquemático:

- Ojo con los operacionales, estás trabajando como inversor, asegurate que a la salida obtengas una tensión positiva.

- En cuanto a las protección en las entradas analógicas del PIC parecen estar bien (no veo valores).

- No alcanzo a ver si juntas las masas (GND) que van al "+" de los operacionales con el circuito (es necesario hacerlo, pero en un solo punto).

En cuanto al PCB:

- Pistas anchas, si podés ensancha lo máximo que puedas, más allá del consumo, ensanchando matás la inductancia parásita de la pista. Por otro lado también tené en cuenta el consumo (con ese circuito no deberías tener mucho consumo), te recomiendo poner la lupa en las pistas de alimentación.

- El cristal debe estar lo más cerca posible de los pines del uC y con pistas los más cortas y anchas posibles. Por otro lado se aconseja que los dos capacitores estén entre el cristal y el uC.

- Faltan capacitores de desacople bien al lado de la alimentación del PIC, del TL084 y el LCD (100nF o más según recomiende el fabricante).

- Si bien las masas (GND) digitales y analógicas son el mismo potencial, en un PCB las tenés que aislar bien después de un cierto punto (ej. el regulador de tensión) y no juntarlas más. Por lo tanto la masa analógica que va al PIC tiene que estar separada de la masa digital del PIC.

- Evitá lazos con la masa, es decir, separá tu circuito en varias etapas, ejemplo => PIC, LCD y Operacionales. Al pic mandale una masa desde el regulador y desde ahí repartís a todo lo involucrado al PIC menos la parte analógica y el LCD. Al LCD también le mandás una linea de masa desde regulador y lo repartís en todos los pines del LCD que necesiten masa. También operacional y la parte analógica del PIC (GND de los zeners y pin AGND) mandás una linea de masa desde el regulador. Nunca juntes las masas de esas etapas.

- De c/etapa que mencioné antes, haces planos de masas bien separados, es decir no sirve llenar todo el resto del cobre que no usas con cualquier GND, tenés que separarlos bien.

- La referencia de tensión para el ADC del PIC también separala y filtrala bien con capacitores e inductores de choque.

Creo que con eso podés mejorar muchísimo el PCB.
 
#73
Código:
while (true)
   {
   set_adc_channel(0);
   delay_us(20);
   for(var1=0;var1<8;var1++)
   {
      volt = read_adc();
      delay_us(20);
   }
   
  var2=var2+volt;
  var1=var1+1;
   valor=volt/8;
   valor=volt*50/1023;
   lcd_gotoxy(2,2);
   printf(lcd_putc,"%04.2f",valor );
   delay_ms(500);
asi estaría bien el código para hacer un promedio de variables
 
#74
Código:
while (true)
   {
   set_adc_channel(0);
   delay_us(20);
   for(var1=0;var1<8;var1++)
   {
      volt = read_adc();
      delay_us(20);
   }
   
  var2=var2+volt;
  var1=var1+1;
   valor=volt/8;
   valor=volt*50/1023;
   lcd_gotoxy(2,2);
   printf(lcd_putc,"%04.2f",valor );
   delay_ms(500);
Así estaría bien el código para hacer un promedio de variables
Nop. Así sólo estás leyendo 9 veces el canal 0 y eso no produce ninguna lectura promedio.
Tienes que ir sumando la lectura dentro del bucle y al final divides el resultado entre la cantidad de muestras.
 
#75
Código:
#include <16f873a.h>
#device adc=10
#fuses NOWDT,BROWNOUT,XT,NOLVP,PUT
#use delay (clock=4m) 
#define use_portb_lcd true
#include <lcd.c>

void main(){
int var1=0;
float valor=0,volt=0,valor2,amper;
//Se habilita el A/D y se declara el PORT a usar
setup_adc_ports(an0_an1_an3);
setup_adc(adc_clock_div_32 ); 


//Se inicia la LCD
lcd_init();
lcd_gotoxy(3,1);
lcd_putc("iniciando");
delay_ms(2000);
lcd_gotoxy(7,2);
lcd_putc("LPK");

delay_ms(500);
lcd_putc("\f");
lcd_gotoxy(2,1);
lcd_putc("Volt Amper");
delay_ms(1000);


while (true){
set_adc_channel(0); 
delay_us(20);
{
for(var1=0;var1<8;var1++)
{
volt=volt+ read_adc();
delay_us(62);


valor = volt / 8;

valor = valor * 50 / 1023;
lcd_gotoxy(2,2);
printf(lcd_putc,"%04.2f",valor);
}

set_adc_channel(3); 
delay_us(20);
amper = read_adc();
delay_us(500);
valor2=amper*18/1023;
lcd_gotoxy(11,2);
printf(lcd_putc,"%04.3f",valor2);
delay_ms(200);

}
}
}
Ahora lo modifiqué pero me arranca sin parar cuando toma la medición de voltaje.
 

Adjuntos

Última edición por un moderador:
#76
Estás matando al pobre uC con las variables flotantes. :LOL:

Acá:

Código:
while(1)
{
  ...
  for(var1=0;var1<8;var1++)
  {
    volt=volt+ read_adc();
    delay_us(62);
  
    valor = volt / 8;

    valor = valor * 50 / 1023;
    lcd_gotoxy(2,2);
    printf(lcd_putc,"%04.2f",valor);
  }
}
Debería quedarte así:

Código:
while(1)
{
  ...
  volt=0;
  for(var1=0;var1<8;var1++)
  {
    volt=volt+ read_adc();
    delay_us(62);  
  }

  valor = volt / 8;

  valor = valor * 50 / 1023;
  lcd_gotoxy(2,2);
  printf(lcd_putc,"%04.2f",valor);
}
Te recomiendo hacer un promedio móvil, para lo cual será necesario usar un vector que contenga las distintas muestras.
 
#78
Acá tenés algo en AVR, pero como es C, es lo mismo (incluso usé ese mismo código en ARM):
https://www.forosdeelectronica.com/posts/911848/
En tu caso sería hacer algo así:

Código:
#define MUESTRAS_MAX 16 // promedio 16 muestras
#typedef unsigned char u8;
#typedef unsigned int u16;

int main(void)
{
  u16 muestras[MUESTRAS_MAX]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //Vector donde almacenaré las muestras => inicializo las muestras en 0.
  u8 indice_muestras=0; //Indice que irá cambiando a medida que obtenga las muestras => armo una cola circular con el vector "muestras"
  
  u16 promedio_movil=0; // Lo uso como variable que indica el resultado  
  
  float valor_resultante;
  //.... inicialización necesaria, entre ellos el ADC

  while(1)
  { 
    //.... Código de la rutina
    
    muestras[indice_muestras]=read_adc();
      
    indice_muestras++;
    if(indice_muestras==MUESTRAS_MAX) //Condición para hacer una cola circular, llegado a 16 muestras, piso el dato más viejo y lo descarto
      indice_muestras=0;
    
    promediar_datos(muestras,&promedio_movil); //Función previamente definida, acá se obtendrá el promedio móvil
               
    valor_resultante=promedio_movil;
    valor_resultante = valor_resultante * 50 / 1024;   
    lcd_gotoxy(2,2);
    printf(lcd_putc,"%04.2f",valor_resultante);

    delay_us(62); 
  }  
}
La función "promediar_datos" te queda igual que la del mensaje.

De todas formas te recomiendo que un futuro, evites los delays usando timers y como en la rutina que hice en el otro mensaje, evitar el hecho de tener que imprimir el resultado toooodo el tiempo.

El promedio móvil a diferencia del promedio anterior, no descarta todas las muestras en el resultado, es decir:

- En el código anterior tomás 8 muestras y obtenés un promedio. Entre medición y medición, descartaste las 8 mediciones anteriores.

- Con este código, tomás las 8 muestras, obtenés su promedio y en la próxima medición, solo descartás 1 muestra para promediar las últimas 8 muestras.
 
Última edición:
Estado
Cerrado para nuevas respuestas.

Temas similares

Arriba