Banner publicitario de PCBWay

Control de potenciómetro digital

Hola! Quiero usar la familia de potenciómetros digitales X9C104 y X9C503 https://www.intersil.com/content/dam/Intersil/documents/x9c1/x9c102-103-104-503.pdf y estoy teniendo problemas con el control en lenguaje C.

He leído el datasheet, teniendo el cuenta todos los aspectos pero sólo soy capaz de hacer "subir" el wiper, no puedo bajarlo y no se qué hacer. Os muestro el código por si se me está escapando algo (los delay los he puesto tan altos por hacer pruebas, lo tengo a 5 ms normalmente)

Código:
#define Dpot_increment  PIN_A4    // POT1
#define Dpot_direction  PIN_A2    // POT2
#define Dpot_select     PIN_A0    // POT3



int target_value;         // sus valores son definidos en el .c principal
int current_value;       // sus valores son definidos en el .c principal

int Dpot(){

output_high(Dpot_increment);

   if (target_value > current_value) { 
   delay_ms(50);
     output_low(Dpot_select) ;    // changes available
    delay_ms(50);
     output_high(Dpot_direction) ; //subir
     
      for (int i = target_value - current_value; i>0;  i--){
         delay_ms(50);
        output_high(Dpot_increment);
         delay_ms(50);
        output_low(Dpot_increment);  
         output_high(pin_b3);   // enciende led verde
         
      }
      }
      
     if (target_value < current_value) {
      delay_ms(50);
      output_low(Dpot_select);    // changes available
        delay_ms(50);
      output_low(Dpot_direction); //BAJAR
      
         for (int j = (current_value - target_value); j>0;  j--){
         delay_ms(50);
         output_high(Dpot_increment);
         delay_ms(50);
         output_low(Dpot_increment);
           output_high(pin_b0);  //enciende led rojo 
                 
      }
      }
      
   delay_ms(100); 
  output_high(Dpot_increment);   
   delay_ms(100); 
  output_high(Dpot_select);              //configuración para guardar en memoria no volátil
   delay_ms(100);
   
   
   output_low(pin_b3);
    output_low(pin_b0);
   return 0;
}

Gracias de antemano, si conocéis un código que funcione os lo agradecería, porque no entiendo el problema :(
 
Aqui te muestro un test que realize hace mucho, dale una leida y me cuentas que tal funciono.

Código:
/*botones de control*/
#define arriba      pin_c1
#define abajo       pin_c2
/********************/


/*atenuador*/
#define  up_down     pin_d0   //1--> arriba   0--> abajo    
#define  select      pin_d1   //0--> se activa cambio  1--> se desactiva cambio
#define  increment   pin_d2   //1--> para activar el incremento y decremento
/**********/


/*funciones a usar*/
void reincia_pot(void);
/**************/


void main()
{

delay_ms(1000);
output_high(select); 
reincia_pot();


   while(true)
   {


 if(input(arriba)==1)	//incremeta
      {
      output_high(up_down);
      delay_ms(10);
      output_low(select); //se activa el cambio de R
      delay_ms(10);
      output_high(increment);
      delay_ms(100);
      output_low(increment);
      output_high(select); //se desactiva el cambio de R      
      }
      
   else if(input(abajo)==1)	//decrementa
      {     
      output_low(up_down);
      delay_ms(10);
      output_low(select); //se activa el cambio de R
      delay_ms(10);
      output_high(increment);
      delay_ms(100);
      output_low(increment);      
      output_high(select); //se desactiva el cambio de R            
      }
      


   }
}//fin de main 


 
   
   
void reincia_pot(void)	//decrementa al maximo
{
int a;

   for(a=0;a<100;a++)
   {
   output_low(up_down);
   delay_us(10);
   output_low(select); //se activa el cambio de R
   delay_us(10);
   output_high(increment);
   delay_us(10);
   output_low(increment);      
   output_high(select); //se desactiva el cambio de R
   }

}

Codigo probado, funciona al 100.
 
Última edición:
En tu código no tienes rutina principal <main> ni un bucle infinito <while>, así que tu código carece de programación en lenguaje C para el control constante de una variable. El código de solhaz tiene mas sentido porque sigue el protocolo de programación en lenguaje C.
 
Aqui te muestro un test que realize hace mucho, dale una leida y me cuentas que tal funciono.

Código:
/*botones de control*/
#define arriba      pin_c1
#define abajo       pin_c2
/********************/


/*atenuador*/
#define  up_down     pin_d0   //1--> arriba   0--> abajo    
#define  select      pin_d1   //0--> se activa cambio  1--> se desactiva cambio
#define  increment   pin_d2   //1--> para activar el incremento y decremento
/**********/


/*funciones a usar*/
void reincia_pot(void);
/**************/


void main()
{

delay_ms(1000);
output_high(select); 
reincia_pot();


   while(true)
   {


 if(input(arriba)==1)	//incremeta
      {
      output_high(up_down);
      delay_ms(10);
      output_low(select); //se activa el cambio de R
      delay_ms(10);
      output_high(increment);
      delay_ms(100);
      output_low(increment);
      output_high(select); //se desactiva el cambio de R      
      }
      
   else if(input(abajo)==1)	//decrementa
      {     
      output_low(up_down);
      delay_ms(10);
      output_low(select); //se activa el cambio de R
      delay_ms(10);
      output_high(increment);
      delay_ms(100);
      output_low(increment);      
      output_high(select); //se desactiva el cambio de R            
      }
      


   }
}//fin de main 


 
   
   
void reincia_pot(void)	//decrementa al maximo
{
int a;

   for(a=0;a<100;a++)
   {
   output_low(up_down);
   delay_us(10);
   output_low(select); //se activa el cambio de R
   delay_us(10);
   output_high(increment);
   delay_us(10);
   output_low(increment);      
   output_high(select); //se desactiva el cambio de R
   }

}

Codigo probado, funciona al 100.


Voy a trastear con él y ahora te digo. Muchas gracias!



En tu código no tienes rutina principal <main> ni un bucle infinito <while>, así que tu código carece de programación en lenguaje C para el control constante de una variable. El código de solhaz tiene mas sentido porque sigue el protocolo de programación en lenguaje C.

Hola! Gracias por la respuesta pero el código que he posteado es un ".c"a parte del codigo principal. Quiero decir que por medio de un #include y llamando a la función Dpot( ); lo quiero ejecutar. Todo esto para no saturar mucho el principal.

Aún así voy a probar el de solhaz que pinta bien.

Saludos!
 
Última edición:
No consigo que X9C503 funcione con ESP32 pero si con Arduino Mega.

Que necesito --> Poder manejar el X9C503 para bajar el volumen de una entrada de línea de audio. No quiero usar potenciómetro manuales comunes.

Esquema X9C503:
INC__| o o | VCC
U/D__| o o | CS
RH___| o o | RL
GND__| o o | Rwiper

En mi caso:
INC------| o o | VCC (5v)
U/D------| o o | GND
Audio in | o o | GND
GND------| o o | Salida

En Arduino Mega conecto todo directamente a la placa y el funcionamiento es correcto.

En ESP32 si lo conecto a la placa no funciona, así que he usado el diodo 2N3904 para los pines 'INC' y 'U/D' (también he probado con 'CS' pero Arduino Mega lo hace bien estando a tierra), y funciona pero no lo hace bien, describo el problema:

Hay que introducir valores entre 0 y 99, y en general lo hace bien, para valores bajos el volumen baja y para valores altos el volumen sube. El problema lo detecté introduciendo siempre el mismo valor. En este caso fue el '91', si lo introduzco varias veces seguidas obtengo distintos resultados, normalmente el volumen se mantiene constante pero a veces sube, otras baja e incluso se produce el silencio total

Con Arduino Mega introduzco el '91' 500 veces y el volumen no cambia nunca, es constante y su funcionamiento es siempre correcto.

¿Cuál puede ser el problema?
¿Que otro componente puedo usar?

Como alternativa he probado con el FM62429, con ESP32 funciona correctamente, pero tiene la función de amplificar que no me viene bien. Para la entrada de línea ya uso resistencias de 22k, luego el potenciómetro y por último el MSGEQ7, no tiene mucho sentido cambiar un potenciómetro para bajar el voltaje y sustituirlo por un componente que puede amplificar. Puedo limitar por código el FM62429 por ejemplo al 60% y sólo usarlo para bajar el volumen aunque no creo que sea una solución muy elegante.

Audio Line In -> resistencias de 22k;-> X9C503 -> MSGEQ7
Audio Line In -> resistencias de 22k;-> FM62429 -> MSGEQ7

Alguna idea o sugerencia?

Código:
#include "X9C10X.h"
#define CSPIN 33
#define INCPIN 14
#define UDPIN 27
X9C503 pot;
void setup() {
  Serial.begin(9600);
  pot.begin(INCPIN, UDPIN, CSPIN);  //  pulse, direction, select
  Serial.println("Introduce un valor entre 1 y 99");
}
void loop() {
  if(Serial.available() != 0){
    int value = Serial.parseInt();
    if (value != 0) {
      pot.setPosition(value, true);
      delay(30);
      Serial.print("Valor introducido: ");
      Serial.println(value);
    }
  }
  delay(100);
}
 
2N3904 no es un diodo, no veo el circuito, pero considerando los voltajes mínimos y máximos, eso lo puedes conectar directamente al ESP32 sin inconvenientes ya que ocupa H en 2V y L en 0.8V. Agrega el circuito ¿los números que das son en GP o en la numeración de la placa?
 
eso lo puedes conectar directamente al ESP32 sin inconvenientes ya que ocupa H en 2V y L en 0.8V
Aunque el nivel lógico alto de salida de ESP32 se espera que sea mayor o igual a 2.45V, se ha visto muchas veces valores bastante mas bajos...cerca de 1.8V. El X9C503 es un dispositivo compatible con TTL, no con CMOS de 3.3V, así que es bastante desafortunado excitar este dispositivo con un nivel lógico - en teoría - marginalmente superior al que especifica el datasheet.
La solución es la de siempre en los ESP32: usar un convertidor de niveles SIN INVERSION a la salida, y no hay que dar mas vueltas el tema a menos que esta solución no funcione...cosa que dudo seriamente por que con el Arduino va OK.
 
Es raro porque el chip es CMOS, no debería drenar una corriente tan grande como para no cumplir lo que en teoría brinda el ESP32, que sea compatible con los niveles TTL es solo en el voltaje, la corriente es significativamente menor como para no operar con lógica CMOS de 3.3V.

En cualquier caso, primero veamos que circuito se está utilizando, sin datos completos no se puede opinar.
 
Buenas gente! Gracias por vuestra colaboración!!

Hasta donde he podido averiguar el X9C503 que tengo en mis manos trabaja a 5V, si se conecta a un Arduino Mega funciona correctamente, pero para poder usarlo en ESP32 hay que hacer uso de transistores.

El problema es que no tengo mucha experiencia y no sabía que con los transistores tenía que usar las resistencias de 4k7 a tierra para que pueda alcanzar el estado LOW. Ahora funciona correctamente, para la misma entrada siempre la misma salida.

A tener en cuenta que el X9C503 es uno barato comprado en AliExpress, compré 4 y 1 no funciona.

Ten en cuenta que lo mismo que se ha hecho con 'INC' Y 'U/D' debes hacerlo con 'CS' si quieres que el valor seleccionado de la resistencia se almacene. Yo no necesito que persista así que lo dejo a tierra y en el código selecciono un pin libre que no vaya a usar. Aunque el pin no se vaya a usar no se puede seleccionar cualquiera que esté libre, si seleccionas un pin y no es bueno no te preocupes, cada vez que intentes cambiar el valor de la resistencia te mostrará un mensaje de error por consola y así podrás seleccionar otro que no falle.

El código que lo hace funcionar es el mismo que publiqué al inicio

solucion.png
Leer el datasheet del X9C503 y del ESP32 y ENTENDER LO QUE DICE.
No eres nada agradable, por muchos conocimientos que creas tener te los puedes quedar sólo para ti con esa actitud. Yo soy programador y no me intento reír de quien sabe menos o no sabe interpretar cosas que yo aprendí o estudié. Y decía que la solución era un inversor y que no se equivocaba juas juas juas
 
Última edición:
Ah, sí, así no se usa, prueba esto para subir el nivel:
LevelUp.png
IO1 al subir hará que la corriente BE sea nula por lo que el transistor no conduce y C se va hasta los 5V, cuando IO1 baja entonces el transistor conduce y también baja el voltaje al otro lado.

Si funciona con el circuito que pones, realmente los transistores están sobrados porque están como un seguidor y aparte de la perdida de tensión por el voltaje BE, tienes perdida por la división por lo que el voltaje que recibe en realidad es menor que el del pin del ESP32, si ocupas 4k7Ohms para que el voltaje baje a LOW, probablemente tu módulo tenga alguna polarización causando que no baje dado a que ese circuito coloca en Z la salida en LOW. Probablemente por la capacitancia parásita en el pin, la resistencia elevada causaría que tarde en descargarse.

Podrías quitar el transistor y conectar los pines directos, como solo son entradas debería ser compatible, si fuera I2C (comunicación bidireccional que debe ir a una resistencia en H) entonces necesitarías el adaptador de niveles, pero para este caso no lo creo.
 
Última edición:
Última edición:
Atrás
Arriba