Cómo estabilizar la pantalla de salida adc en 7 segmentos

Estoy diseñando un voltímetro simple. Estoy usando ADC de 8 bits de PIC16F72 y el compilador Mikro C con una pantalla multiplexada de 7 segmentos. Obtengo el valor ADC en la pantalla de 7 segmentos, pero fluctúa continuamente (por ejemplo, 1670 mV fluctúa entre 1660 y 1680 mV). Probé todo en hardware, agregando un límite en ADC y tierra, etc.

Aquí está mi código:

void StabilizeVoltage()
{
     unsigned int ADS;
     if (flgAC)
      {
      ADS = ADC_Get_Sample(0);
      Voltage_FLOAT =(float)ADS *19.6078431372549;
      a= Voltage_FLOAT;
      Voltage_INT=a;
      //if(63<Voltage_INT && Voltage_INT<78 )
       if(Voltage_INT <=1050 )
      {
      Relay1=0;
      Relay2=0;
      Relay3=0;
      Relay4=0;
      }
      else if (1050<Voltage_INT && Voltage_INT<=1150)
      {
      Relay1=1;
      Relay2=0;
      Relay3=0;
      Relay4=0;
      }
      else if (1150<Voltage_INT && Voltage_INT<=1350)
      {
      Relay1=1;
      Relay3=1;
      Relay2=0;
      Relay4=0;
      }
      else if (1350<Voltage_INT && Voltage_INT<=1450)
      {
      Relay1=1;
      Relay3=1;
      Relay2=1;
      Relay4=0;
      }
      else if (1450<Voltage_INT )
      {
      Relay1=1;
      Relay3=1;
      Relay2=1;
      Relay4=1;
      }
      }
      flgAC = 1;
}
void main()
{
      InitIO();
      ADC_Init();
      InitTimer2();
      InitDisplay();
     while(1)
     {
         UpdateDisplay();
         StabilizeVoltage();
     }
}

¿Necesito algún filtro de software?

ingrese la descripción de la imagen aquí

Usted dice que probó 'todo', ¿puede agregar un diagrama de circuito para que podamos ver más claramente lo que tiene hasta ahora?
¿Hay un límite de ~100 nF en los rieles de alimentación cerca de los pines de alimentación del PIC?

Respuestas (2)

Una posible solución de software es la media móvil exponencial muy simple de implementar ( http://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average ). Solo requiere una variable global y unas pocas líneas de código. Es un poco más de trabajo para lograrlo, pero esto también se puede hacer con un código de punto fijo (es decir, int) para una eficiencia mucho mayor (no me preocuparía si todo lo que hace es leer un ADC y mostrarlo).

Por ejemplo:

//K is the filter coefficient and must be smaller than 1 and greater than zero (0<K<1)
//The smaller the K is, the more the filter will smooth, but it will also take longer
//to reach its value when the input changes.
#define K 0.01f

float filter( float aData )
{
    static float memory;
    memory = memory*(1-K) + aData*K;
    return memory;
}

Estás viendo tramado de ese bit menos significativo mientras intenta decidir si ser un 1 o un 0; es algo con lo que deberá lidiar escalando la entrada al ADC, a menos que pueda ignorar la fluctuación de la pantalla.

Ese último bit siempre oscilará un poco a menos que esté midiendo voltajes que sean MUY estables y no esté captando NINGÚN ruido de fuentes externas. Puede hacerlo un poco más silencioso si puede reducir su impedancia de entrada, si el difuminado es el resultado del ruido exterior. Sin embargo, cada vez que el voltaje que mide no es estable dentro del 1,2%, verá ese tipo de difuminado en el bit menos significativo.

A 1670 mv, su ADC le está dando datos = 85 + - 1. Multiplicado por su ~ 19.6, datos de 84 = 1646.4 (1646), datos de 85 = 1666 y datos de 86 = 1685.6 (1686), por lo que vea cualquier cosa desde 1646 a 1686 dependiendo de si su bit menos significativo elige 1 o 0.

Escale la entrada al ADC con un amplificador operacional con una ganancia de 19.6, y puede eliminar la multiplicación de su software y leer voltajes directos ... Y su tramado debería aliviarse.