4 votos

¿Cómo controlar el potenciómetro de control digital X9C102?

Tengo un montón de Intersil X9C102P , potenciómetros controlados digitalmente que quiero probar. Estos dispositivos consisten en una matriz de resistencias y algunos interruptores analógicos que seleccionan la combinación de resistencias para dar la resistencia deseada. Por favor, mire el siguiente diagrama:

Basic Block Diagram

Como puede verse en el diagrama anterior, el dispositivo tiene 6 pines excepto los de alimentación. Tres pines a la izquierda son los pines que controlan el wiper del potenciómetro.

Revisa el diagrama de abajo, y verás que básicamente funciona así; un contador Up/Down de 7 bits es controlado con los pines de control que se mencionan arriba. Entonces, el valor de este contador se alimenta a un decodificador de 1 de 100, que controla las puertas de los transistores para conectar la resistencia deseada a la escobilla.

Detailed Block Diagram

Controlar el potenciómetro digital parece fácil, aunque no soy capaz de conseguirlo. Usted da un BAJO a SELECCIONAR CHIP pin mientras INCREMENTO es ALTO y estable, y luego mantienes SELECCIONAR CHIP BAJA.

Para mover el limpiaparabrisas hacia arriba, por lo tanto disminuir la resistencia en mi caso, hacer ARRIBA/ABAJO pin HIGH, entonces haga INCREMENTO baja. En el flanco descendente de INCREMENTO El limpiaparabrisas se mueve hacia arriba.

Para mover el limpiaparabrisas hacia abajo, simplemente aplique el procedimiento anterior con ARRIBA/ABAJO pin BAJO.

Después de que estés contento con el resultado, pasarás al modo de espera y apagarás la lógica dentro del X9C102. Tienes dos opciones; puedes guardar el estado actual en la memoria no volátil del chip, o no guardarlo. Para standby con guardar, haces SELECCIONAR CHIP ALTO cuando INCREMENTO es ALTO. En el flanco ascendente de SELECCIONAR CHIP , el aparato entrará en modo de espera después de guardar el valor, lo que tarda 20 ms. Si no desea guardar al entrar en modo de espera, mantenga pulsado INCREMENTO pin BAJO.

Control Method

Este es el esquema que utilizo para lograr el éxito. Para probar los potenciómetros digitales X9C102P que tengo entre manos muevo el limpiaparabrisas hacia abajo 100 veces, luego lo muevo hacia arriba 50 veces y luego mido el voltaje en WIPER pin. Sin embargo, no puedo lograr el éxito. Así que, por ahora, he escrito un código que mueve el limpiaparabrisas hacia abajo 100 veces y mueve el limpiaparabrisas hacia arriba 100 veces.

Schematic

Código para el PIC16F616 microcontrolador es el siguiente. He intentado volver a dormir sin almacenar después de cada movimiento del limpiaparabrisas, sin embargo eso no cambió el resultado. Aquí está una cita de la hoja de datos al respecto:

Los interruptores electrónicos del dispositivo funcionan "antes de romper". cuando el limpiaparabrisas cambia de posición. Si el rascador se mueve varias posiciones, se conectan varias tomas al rascador para tIW (cambio INC a VW/RW). El valor RTOTAL del dispositivo puede reducirse temporalmente en una cantidad significativa si el rascador se desplaza posiciones.

/* 
 * File:   main.c
 * Author: abdullah
 *
 */

#include <xc.h> // Include the header file needed by the compiler
#define _XTAL_FREQ 4000000 // Internal oscillator is set to 4 MHz.
__CONFIG(FOSC_INTOSCIO & WDTE_OFF & PWRTE_ON & MCLRE_OFF & CP_ON & IOSCFS_4MHZ & BOREN_ON);

#define X9C102_Increment    PORTCbits.RC3
#define X9C102_UpDown       PORTCbits.RC4
#define X9C102_ChipSelect   PORTCbits.RC2
#define wiperReadAnalogCH   ANS5
#define wiperReadAnalogCHN  5
#define statusLED           PORTCbits.RC5  // This LED is the user interface.

unsigned short long ADC_ResultBuffer; // This variable will store ADRESH ADRESL combined.
unsigned char wiperValue = 0; // This value will hold scaled value of ADC_ResultBuffer
unsigned char i = 0; // Generic counter variable.

// Interrupts will wake-up the CPU.

void interrupt myInterrupt(void)
{
    if (INTF) // If there is a falling edge on INT pin,
    {
        INTF = 0; // Clear the interrupt flag.
    }
}

void main(void)
{
    ANSEL = 0; // Make all the pins digital i/o.
    ANSELbits.wiperReadAnalogCH = 1; // Make the wiper pin as analog input.

    TRISA = 0x04; // PORTA.2 is input, other PORTA pins are output.
    TRISC = 0x02; // PORTC.1 is input, other PORTC pins are output.

    X9C102_ChipSelect = 1;
    X9C102_UpDown = 1;
    X9C102_Increment = 1;
    statusLED = 0;

    ADFM = 1; // ADFM: A/D Conversion Result Format Select bit: 1 = Right justified, 0 = Left justified
    ADCON1bits.ADCS = 0x05; // ADCS<2:0>: A/D Conversion Clock Select bits : 101 = FOSC/16, 2us conversion time
    ADCON0bits.CHS = 0; // CHS<3:0>: Analog Channel Select bits : 0 to 7

    INTCONbits.INTE = 1; // Enable interrupt generation on INT interrupt.
    INTCONbits.GIE = 1; //GIE: Global Interrupt Enable bit

    // Power up, notice user by flashing the LED.
    for (i = 0; i < 5; i++)
    {
        statusLED = 1;
        __delay_ms(250);
        statusLED = 0;
        __delay_ms(250);
    }
    asm("sleep"); // Put the CPU to sleep. CPU will wake-up on button press.

    while (1)
    {
        // We have started the test, flash the LED.
        for (i = 0; i < 5; i++)
        {
            statusLED = 1;
            __delay_ms(250);
            statusLED = 0;
            __delay_ms(250);
        }

        // Move wiper down by 100 positions.
        for (i = 0; i < 100; i++)
        {
            X9C102_ChipSelect = 0;
            __delay_ms(1);
            X9C102_UpDown = 0;
            __delay_ms(1);
            X9C102_Increment = 0;
            __delay_ms(1);
            X9C102_Increment = 1;
            __delay_ms(1);
            // Return to sleep without storing.
            X9C102_ChipSelect = 1;
            // Wait for some time to allow debugging with multimeter
            __delay_ms(20);
        }

        // Going to move wiper down, alert user.
        for (i = 0; i < 5; i++)
        {
            statusLED = 1;
            __delay_ms(250);
            statusLED = 0;
            __delay_ms(250);
        }

        // Move wiper up by 100 positions.
        for (i = 0; i < 100; i++)
        {
            X9C102_ChipSelect = 0;
            __delay_ms(1);
            X9C102_UpDown = 1;
            __delay_ms(1);
            X9C102_Increment = 0;
            __delay_ms(1);
            X9C102_Increment = 1;
            __delay_ms(1);
            // Return to sleep without storing.
            X9C102_ChipSelect = 1;
            // Wait for some time to allow debugging with multimeter
            __delay_ms(20);
        }

        // Store the value.
        X9C102_Increment = 1;
        __delay_ms(1);
        X9C102_ChipSelect = 1;
        __delay_ms(25);

        /*
        // Following code is disabled. Normally, it checks the voltage on the
        // wiper pin and notifies user if it is in desired boundary.

        ADON = 1; // Turn the ADC ON.
        ADCON0bits.CHS = wiperReadAnalogCHN; // Select the appropriate analog channel.
        __delay_ms(1); // Wait the required acquisition time.
        GO_nDONE = 1; // Start the conversion.

        while (GO_nDONE);

        // Conversion is complete:
        ADC_ResultBuffer = ADRESL + (unsigned int) (ADRESH << 8); // Combine 8 bit "ADRESH" and  8 bit "ADRESL" to one 24 bit register.
        ADC_ResultBuffer *= 100; // Multiply by 100,
        ADC_ResultBuffer >>= 10; // and divide by 2^10 (1024), which,in turn, is (ADC_RESULT*100)/1024. So, we get a result from 0 to 100.
        wiperValue = (unsigned char) (ADC_ResultBuffer); // Put the result into the relevant variable.

        ADON = 0; // Turn the ADC OFF.

        if (wiperValue > 40 && wiperValue < 60)
        {
            statusLED = 1;
            __delay_ms(2500);
        }
        else
        {
            for (i = 0; i < 5; i++)
            {
                statusLED = 1;
                __delay_ms(250);
                statusLED = 0;
                __delay_ms(250);
            }
        }
         */

        statusLED = 0;
        asm("sleep"); // Put CPU into sleep mode.
    }
}

Cuando mido el pin 5, Rwiper, en el X9C102P, obtengo un valor máximo de 1,5V. Sin embargo este valor difiere de un IC a otro. Salta alrededor de 1.3V a 1.8V, una vez recuerdo haber visto 2.5V. Además, he comprado algunos circuitos integrados nuevos y tienen el mismo problema. Por lo tanto, está claro que tengo un problema con mi circuito o mi código. Además, los pasos no son lineales, son más bien exponenciales, algo así como "2^x". Empiezan a incrementarse con pasos más grandes. Aquí hay capturas del pin 5, Rwiper, mostrando el movimiento del limpiaparabrisas, como se puede ver sólo sube a alrededor de 1,7 V esta vez. ¿Qué causa este comportamiento impar?

Wiper Up Wiper Down Wiper Down Detailed

3voto

Brian Drummond Puntos 27798

Como primer paso, asegúrese de que está midiendo lo que cree que está midiendo. Desconecta el wiper del pin de entrada del PIC, por si la corriente de fuga del pin del PIC está influyendo en tus medidas.

Si este es realmente el problema, la solución normal es conducir la carga (la entrada del PIC) desde una fuente de baja impedancia, es decir, un amplificador tampón. Normalmente se trataría de un amplificador operacional "rail to rail" (las tensiones de entrada y salida pueden oscilar hasta los raíles de alimentación) conectado en configuración de ganancia unitaria.

Pero comprueba también que el software del PIC está configurando correctamente ese pin como entrada. Mirando la hoja de datos del PIC (pin 165) la "fuente de voltaje analógica" debería tener una impedancia < 10k. El X9C102 ya lo hace, (su rango es de hasta 1k) así que tu configuración original debería funcionar.

Intenta tirar del pin PIC alto o bajo con una resistencia de 1k; si no oscila muy cerca de los suministros, tienes un problema de configuración de software (el pin sigue siendo una salida) o posiblemente un PIC dañado. A simple vista tu software parece correcto pero no estoy familiarizado con ese PIC.

3voto

Stephen Denne Puntos 218

Sé que tienes una solución, pero pensé en añadir otra opción, para futuras referencias.

Recientemente he estado utilizando un Pirata del autobús como sustituto de un micro-controlador externo en un sistema en el que estoy trabajando. Por 30 dólares, es una herramienta excelente.

enter image description here

En tu situación, podrías ponerlo en modo "bit-bang", y usarlo para subir y bajar el pote.
También tiene un ADC de 10 bits, que podría utilizar para leer de nuevo el valor del limpiaparabrisas con bastante facilidad.

Si yo estuviera en tu situación, creo que probablemente elegiría algo como esto en lugar de escribir C para un PIC, ya que puedes programar el bus pirata desde un ordenador (en mi caso, estoy usando python).

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X