Pages: [1]   Go Down
Author Topic: [Resuelto] Problema al representar numeros en un display  (Read 1913 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 47
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

El problema que tengo es que si incremento una variable cuando llega al 9 parece que se paran los números hasta que llega al 2 el cual muestra a medias. Y el tres también lo muestra a medias, los siguientes los muestra bien hasta que llega al 9 de nuevo.
Por ejemplo: comienzo desde el 40, pues cuando llega al 50, las unidades se quedan en el 9 y se incrementa las decenas. Cuando llega al 52, el dos sale sin la parte superior y el 53 también. Después el 54 sale bien hasta el 59 que vuelve a pasar lo mismo; se incrementa las decenas y el problema de las unidades se repite.
Se puede pensar que no se representa el 0, el 1 y el 2 por un fallo de programación o de montaje,  pero si comienzo por el 49 el 50, 51, 52 y 53 salen bien.
Probado en Mega 2560 y un clon estilo paperduino. En ambas placas hacen lo mismo.
Os pongo el código:

Code:
int led = 13;
int dispCentenas = 2;
int dispDecenas = 3;
int dispUnidades = 4;
int A = 5;
int B = 6;
int C = 7;
int D = 8;
int number = 49;
int unidad;
int decena;
int centena;
int unidades[4]= {0,0,0,0}; //[3] mayor peso, [0] menor peso
int decenas[4]={0,0,0,0}; //[3] mayor peso, [0] menor peso
int centenas[4]={0,0,0,0}; //[3] mayor peso, [0] menor peso

void setup() {  
  
  pinMode(led, OUTPUT);
  pinMode(dispCentenas, OUTPUT);
  pinMode(dispDecenas, OUTPUT);
  pinMode(dispUnidades, OUTPUT);
  pinMode(A, OUTPUT);
  pinMode(B, OUTPUT);
  pinMode(C, OUTPUT);
  pinMode(D, OUTPUT);
  analogReference(DEFAULT);
  
}


void loop() {
  //number=analogRead(A3);
 number=number+1;
 // number=number/2;
  trocear(number);
  convBinario(unidad, unidades);
  convBinario(decena, decenas);
  convBinario(centena, centenas);
  
  digitalWrite(led, HIGH);
  digitalWrite(dispUnidades, HIGH);
  digitalWrite(dispDecenas, LOW);
  digitalWrite(dispCentenas, LOW);
  digitalWrite(A, unidades[0]);
  digitalWrite(D, unidades[3]);
  digitalWrite(C, unidades[2]);
  digitalWrite(B, unidades[1]);
  delay(400);
  
  digitalWrite(led, LOW);
  digitalWrite(dispUnidades, LOW);
  digitalWrite(dispDecenas, HIGH);
  digitalWrite(dispCentenas, LOW);
  digitalWrite(A, decenas[0]);
  digitalWrite(B, decenas[1]);
  digitalWrite(C, decenas[2]);
  digitalWrite(D, decenas[3]);
  delay(400);
  
  digitalWrite(led, HIGH);
  digitalWrite(dispUnidades, LOW);
  digitalWrite(dispDecenas, LOW);
  digitalWrite(dispCentenas, HIGH);
  digitalWrite(A, centenas[0]);
  digitalWrite(B, centenas[1]);
  digitalWrite(C, centenas[2]);
  digitalWrite(D, centenas[3]);
  delay(400);    

}

void trocear(int numero)
{
  int cociente;
  int cociente2;
  int numero2;
  cociente=numero/10;
  numero2=cociente*10;
  unidad=numero-numero2;
  cociente2=cociente/10;
  numero2=cociente2*10;
  decena=cociente-numero2;
  centena=cociente2;
}

void convBinario (int numero, int vector[4])
{
//  int vector[4]={0,0,0,0};
  int numero2;
  int cociente;
  int cociente2;
  int cociente3;
  
  if (numero != 0)
  {
    cociente=numero/2;
    numero2=cociente*2;
    vector[0]=numero-numero2;
    if (cociente != 0)
    {
      cociente2=cociente/2;
      numero2=cociente2*2;
      vector[1]=cociente-numero2;
      if (cociente2 !=0)
      {
        cociente3=cociente2/2;
        numero2=cociente3*2;
        vector[2]=cociente2-numero2;
        vector[3]=cociente3;
       // return vector[4];
      }
    }
  }
}

« Last Edit: February 14, 2013, 03:58:56 am by iceman_f5 » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 47
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Aprovecho también para decir que me he encontrado otro problema.
Probando las entradas analógicas he conectado un potenciómetro entre 5 voltios y masa, llevando la patilla que se regula a una entrada analógica del Arduino y midiendo al mismo tiempo la tensión de esa patilla. Eso dentro del programa que he puesto antes. Se puede ver en las líneas de código puestas como comentario.
Pues bajando la tensión cuando llegaba a más o menos 1,7 voltios saltaba de darme 200 y algo a darme 700 y algo. Como si hubiera un salto ascendente de tensión cuando realmente había disminuido.
¿A qué puede deberse?
Logged

Palencia, Spain
Offline Offline
God Member
*****
Karma: 25
Posts: 502
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hola, iceman_f5.
Igual responde el menos indicado, porque aún no estoy muy puesto en electrónica, pero entiendo que se trata de displays numéricos, de segmentos o algo así, ¿no?
¿No puede ser que el problema venga dado porque modifiques el número mientras tienes activado el dígito correspondiente? es decir, ¿no deberían estar los selectores en LOW y poner el selector correspondiente en HIGH durante x microsegundos después de "tener escrito" el número? Si estoy en lo correcto, lo lógico es que en el setup estuvieran todos los selectores en LOW. Entonces, para cada dígito, primero escribiríamos ABCD, luego activaríamos unidades, decenas o centenas, esperaríamos x microsegundos, y luego la desactivaríamos para que queden todas en LOW. Algo así como:

  digitalWrite(led, HIGH);
  digitalWrite(A, unidades[0]);
  digitalWrite(D, unidades[3]);
  digitalWrite(C, unidades[2]);
  digitalWrite(B, unidades[1]);
  digitalWrite(dispUnidades, HIGH);
  delay(400);
  digitalWrite(dispUnidades, LOW);

Si funcionara así, ya me dirás, y si no, a ver si alguien puede arrojar más luz.
Luego, como crítica constructiva, me parece que tu código es un poco lioso (manda narices que yo diga eso, con los churros que me salen  smiley-mr-green). En primer lugar, porque para "trocear" el número en unidades, decenas y centenas, sería más sencillo tirar del operador módulo (%) que te devuelve el resto de una división. Algo así como:

void trocear(int numero)
{
  unidad=numero %10;
  numero/=10;
  decena=numero % 10;
  numero/=10;
  centena=numero %10;
}

Y en segundo lugar, la conversión de los dígitos a binario no debería ser necesaria (en el micro ya está en binario  smiley) teniendo funciones a nivel binario rápidas y sencillas:
A=unidades & 0001b
B=unidades & 0010b
C=unidades & 0100b
D=unidades &1000b
Incluso ni esto sería necesario, si eliges bien los pines ABCD.

Espero no haberme equivocado y haber ayudado.
Saludos
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 47
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Utilizo un display de siete segmentos y tres dígitos con un decodificador BCD-7 segmentos.
Sí que se está modificando el número mientras está activo el dígito, pero supongo que no debería haber problema con eso ya que es un circuito combinacional. Y debido a que esos cambios se producen rápido no se aprecian. Aunque activase el dígito cuando he enviado los 4 bits, el funcionamiento sería el mismo. No puedo activar los tres dígitos por un lado porque el display no lo permite; hay que multiplexarlo.

No conocía el operador %, por lo que tuve que hacer las conversiones de la manera que ves. De haberlo sabido no me habría complicado tanto.
Y tienes razón también en la forma de implementar las dos funciones, las tuyas son más eficientes. Se nota que sabes más de programación que yo.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 47
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Con el código así funciona todo correctamente; los displays y la entrada analógica.
No se qué fallaba antes ya que a pesar de ser un código poco eficiente, creo que era correcto.


Code:
int led = 13;
int dispCentenas = 2;
int dispDecenas = 3;
int dispUnidades = 4;
int A = 5;
int B = 6;
int C = 7;
int D = 8;
int number = 49;
int unidades;
int decenas;
int centenas;

void setup() {  
  
  pinMode(led, OUTPUT);
  pinMode(dispCentenas, OUTPUT);
  pinMode(dispDecenas, OUTPUT);
  pinMode(dispUnidades, OUTPUT);
  pinMode(A, OUTPUT);
  pinMode(B, OUTPUT);
  pinMode(C, OUTPUT);
  pinMode(D, OUTPUT);
  analogReference(DEFAULT);
  
}

void loop() {
  number=analogRead(A3);
  trocear(number);
  
  digitalWrite(led, HIGH);
  digitalWrite(dispUnidades, LOW);
  digitalWrite(dispDecenas, LOW);
  digitalWrite(dispCentenas, LOW);
  digitalWrite(A, unidades & B0001);
  digitalWrite(B, unidades & B0010);
  digitalWrite(C, unidades & B0100);
  digitalWrite(D, unidades & B1000);
  digitalWrite(dispUnidades, HIGH);
  delay(400);
  
  digitalWrite(led, LOW);
  digitalWrite(dispUnidades, LOW);
  digitalWrite(dispDecenas, LOW);
  digitalWrite(dispCentenas, LOW);
  digitalWrite(A, decenas & B0001);
  digitalWrite(B, decenas & B0010);
  digitalWrite(C, decenas & B0100);
  digitalWrite(D, decenas & B1000);
  digitalWrite(dispDecenas, HIGH);
  delay(400);
  
  digitalWrite(led, HIGH);
  digitalWrite(dispUnidades, LOW);
  digitalWrite(dispDecenas, LOW);
  digitalWrite(dispCentenas, LOW);
  digitalWrite(A, centenas & B0001);
  digitalWrite(B, centenas & B0010);
  digitalWrite(C, centenas & B0100);
  digitalWrite(D, centenas & B1000);
  digitalWrite(dispCentenas, HIGH);
  delay(400);    

}

void trocear(int numero)
{
  unidades=numero %10;
  numero/=10;
  decenas=numero % 10;
  numero/=10;
  centenas=numero %10;
}

Gracias a noter por las críticas constructivas. Parece que son las que han resuelto el problema.
« Last Edit: February 14, 2013, 04:01:00 am by iceman_f5 » Logged

Palencia, Spain
Offline Offline
God Member
*****
Karma: 25
Posts: 502
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ten en cuenta que en tu primer programa, aunque sea por unos pocos microsegundos, el número BCD que tienes en los pines va cambiando dígito a dígito estando activo el pin selector. También ten en cuenta que durante unos pocos microsegundos, también tenías dos selectores activados simultáneamente (cuando terminaba el ciclo, estando activadas las centenas, inicias poniendo activas las unidades y, después desactivas las decenas, estando ahí durante unos pocos ciclos activas simultáneamente unidades y centenas). Por ello es más sencillo y seguro, y consume menos ciclos lo que te recomendaba, de iniciar en setup con todos en LOW, y para cada dígito preparar el número, activar su selector (no hace falta desactivar los otros, pues sabemos que partimos de todos en LOW), delay y desactivar su selector, con lo que sabes que lo has vuelto a dejar de nuevo todo en LOW.
Si tienes interés en aprender algo interesante, también te comento que si todos los pines están en el mismo puerto y bien ordenados, puedes casi escribir directamente el dígito en el puerto, en lugar de bit a bit. Sólo tienes que "sumarle" el selector. Así para escribir 7 en las unidades, decenas o centenas, tendrías que escribir 7+(16,32 o 64) en el puerto o, hablando en binario, 0001-0111, 0010-0111, 0100-0111.
Saludos, y espero no haberte liado en lugar de aclarado smiley-wink.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 47
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Mi idea era enviar los datos por puertos como se hace en los PICs, pero he tomado la idea de que en Arduino no existe esa posibilidad y hay que hacerlo todo pin a pin.
¿En lo que dices "sumarle" te refieres a concatenar? Si es asi, entiendo la idea.
No se cómo enviar los datos por puertos en Arduino, pero sí que me interesaría aprenderlo.
Estoy bastante perdido en esta plataforma  smiley-confuse
Logged

Palencia, Spain
Offline Offline
God Member
*****
Karma: 25
Posts: 502
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Pues, efectivamente el atmel también usa puertos, aunque en la programación "normal" se usan las funciones de pin (internamente se convierten en operaciones sobre el puerto) principalmente porque al manipular un puerto hay que tener cuidadín de qué pines estás tocando, amén de que no todos los pines de un puerto siempre corresponden a pines e/s, pero para casos como el que tienes entre manos podrías utilizar directamente el puerto D, que mapea los pines digitales 0 al 7 (0-3 para líneas ABCD y 4-7 para selector unidades, decenas, centenas y millares).
Para escribir el número 1357 habría que escribir en portd, con sus respectivas pausas los siguientes números en hexadecimal (se ve más claro):
81h (80h=128d=millares, + el 1)
43h (40h=64d=centenas, + 3)
25h (20h=32d=decenas, +5)
17h(10h=16d=unidades, +7)
Lo de sumar, como ves, literalmente funcionaría en este caso, aunque no es lo más correcto (son más claras y seguras) es utilizar las operaciones de bit, pero no quisiera liarte, pues no sé si te sientes cómodo con los número binarios y hexadecimales.


manipulación de puertos y Operadores a nivel de bits
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 47
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

No te preocupes por liarme. No temo a nada!  smiley-razz
Intentaré comprender lo que me escribas. Podría trabajar con números hexadecimales, decimales, binarios,... Lo que mejor sea o con lo que mejor me aclare es lo que utilizaré, pero no por ello debe la gente evitar explicarme las cosas en el modo que vea más correcto.
He programado PICs, y no es que sea experto, pero no es mi primer contacto con un microcontrolador; es el segundo  smiley-yell.

Entiendo lo que me dices. No he trabajado mucho con números hexadecimales, pero si es la forma de usar los puertos habrá que pensar en hexadecimal. En cualquier caso queda más "recogido" que escribiendo los 8 bits en binario.
Logged

Palencia, Spain
Offline Offline
God Member
*****
Karma: 25
Posts: 502
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Pues básicamente, dividimos el puerto en dos partes. Los bit 0-3 son directamente el número binario que representa al dígito que vamos a escribir (no hace falta ni convertirlo, si las líneas ABCD van a los pines 0123), y los 4 de arriba son el selector. Entonces, para construir el número a escribir en portd, tenemos que mezclar el número correspondiente al dígito y que va de 0 a 9 (00000000 a 00001001) con el selector , que podrá ser 00010000,00100000,01000000 y 10000000. Si sumamos, o mejor hacemos un or a nivel bit, entre el dígito a representar, y el número que activa al selector, y escribimos ese número en el puerto, tenemos simultáneamente las líneas de dígito y selector activadas. Por ejemplo para escribir un 5 e centenas, hacemos la operación
00000101:  5
01000000:  Centenas
01000101:  resultante
en código sería algo así como:

#define SELUNIDADES=00010000b;
#define SELDECENAS= 00100000b;
#define SELCENTENAS=01000000b;
#define SELMILES= 10000000b;

void escribevalor(int valor){
byte digito=valor%10;
PORTD=SELUNIDADES|digito;
delay(400);
valor/=10;
digito=valor%10;
PORTD=SELDECENAS|digito;
delay(400);
valor/=10;
digito=valor%10;
PORTD=SELCENTENAS|digito;
delay(400);
valor/=10;
digito=valor%10;
PORTD=SELMILES|digito;
delay(400);
}
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 47
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

¡Cómo se nota os que sabéis, que además de hacer las cosas lo hacéis con eficiencia!
Yo me complico bastante para hacer las cosas como puedes ver.
O a veces ni las soluciono como también se puede ver  smiley-confuse
Poco a poco iré cogiendo manejo al lenguaje.
Logged

Pages: [1]   Go Up
Jump to: