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:
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.
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.
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.
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?