domingo, 19 de enero de 2014

Controlar una matriz barriendo filas y barriendo columnas (74HC595)

 En los dos casos es la misma matriz. La he generado con el ArduinoFrameAnimator.jar y no se parece en nada. Además, genera una matriz de 64 elementos. Tal vez genere las filas y las columnas. Lo pongo aquí por si algún día estoy inspirado y consigo verlo.
código generado por ArduinoFrameAnimator.jar:
int animationFrames = 1;

int animationDelays[] = { 200 };

// Animation is designed for 16x16 pixels
uint8_t animation[][64] = {
  { 0x3, 0x0, 0x0, 0xc0, 0xc, 0x0, 0x0, 0xc0, 0x30, 0x0, 0x0, 0xc0, 0xc0, 0x0, 0x0, 0xc0, 0x0, 0x3, 0x0, 0xc0, 0x0, 0xc, 0x0, 0xc0, 0x0, 0x30, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0x0, 0x3, 0xc0, 0x0, 0x0, 0xc, 0xc0, 0x0, 0x0, 0x30, 0xc0, 0x0, 0x0, 0xc0, 0xc0, 0x0, 0x0, 0x0, 0xc3, 0x0, 0x0, 0x0, 0xcc, 0x0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0x0, 0xc0 }
};

CONCLUSION:

Sale mejor barriendo filas porque el led que corresponda a la columna que se enciende lo hará con la máxima intensidad.
Eso tiene la desventaja de que es más dificil escribir la matriz. En este caso la he escrito en positivo y después la he invertido mediante una operación OR EXclusivo a cada uno de los elementos de la matriz.
Pongo primero el código de barrido de columnas por ser más intuitivo. Además, así se puede apreciar el cambio de luminosidad de la última columna.
Para hacer un barrido rápido y continuo basta con comentar la línea delay.

Barriendo columnas

Se muestra el contenido de la matriz que se muestra haciendo un barrido por columnas.

código:
//salidas que se van a utilizar
byte latchPin = 8;
byte clockPin = 12;
byte dataPin = 11;
//array en el que se va a contener toda la informacion de filas
byte dato[32] = {0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0xFF, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0, 0, 0, 0, 0, 0, 0, 0xff };//informacion de las filas

/*       --
  X00000000000000X
  0X0000000000000X
  00X000000000000X
  000X00000000000X
  0000X0000000000X
  00000X000000000X
  000000X00000000X
- 0000000X0000000X-
- 00000000X000000X-
  000000000X00000X
  0000000000X0000X
  00000000000X000X
  000000000000X00X
  0000000000000X0X
  00000000000000XX
  000000000000000X
         --
*/
byte i;
byte co_L, co_H;

void setup() {
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
}

void loop() {
  muestra (dato);
}

void muestra (byte *matriz) {
  co_L=0xFE;
  co_H=0xFF;
  for (i=0;i<16;i++) {
    digitalWrite(latchPin, 0);
    shiftOut(dataPin, clockPin, MSBFIRST, matriz[i+16]);
    shiftOut(dataPin, clockPin, MSBFIRST, matriz[i]);
    shiftOut(dataPin, clockPin, MSBFIRST, co_H);
    shiftOut(dataPin, clockPin, MSBFIRST, co_L);
    digitalWrite(latchPin, 1);
    if (i<8){
      co_L<<=1;
      bitSet(co_L,0);
    }
    else{
      co_H<<=1;
      bitSet(co_H,0);
    }
    if (i==7){
      co_L=0xFF;
      co_H=0xFE;
    }
    delay(250);
  }
}

Barriendo filas


Mismo programa, misma matriz barriendo filas en vez de columnas. Como la columna de la derecha brillaba menos, deduzco que las resistencias de control están en los cátodos. Barriendo por filas se hace que todas brillen igual. Sigo sin ver como se pasa del arduinoframeanimator.jar a una matriz similar a estas que me salen.

código:
//salidas que se van a utilizar
byte latchPin = 8;
byte clockPin = 12;
byte dataPin = 11;
//array en el que se va a contener toda la informacin de filas
byte dato[32] = {
  0x80, 1, 0x40, 1, 0x20, 1, 0x10, 1, 0x08, 1, 0x04, 1, 0x02, 1, 1, 1, 0, 0x81, 0, 0x41, 0, 0x21, 0, 0x11, 0, 0x09, 0, 0x05, 0, 0x3, 0, 1};//informacion de las columnas

/*       --
 X00000000000000X
 0X0000000000000X
 00X000000000000X
 000X00000000000X
 0000X0000000000X
 00000X000000000X
 000000X00000000X
 - 0000000X0000000X-
 - 00000000X000000X-
 000000000X00000X
 0000000000X0000X
 00000000000X000X
 000000000000X00X
 0000000000000X0X
 00000000000000XX
 000000000000000X
 --
 */
byte i;
byte fi_L, fi_H;

void setup() {
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  for (i=0;i<32;i++) {
    dato[i]^=0xFF;
  }//invierto todos los bits porque las columnas van a los cátodos.
}

void loop() {
  muestra (dato);
}

void muestra (byte *matriz) {
  fi_L=0x01;
  fi_H=0x00;
  for (i=0;i<32;i+=2) {
    digitalWrite(latchPin, 0);
    shiftOut(dataPin, clockPin, LSBFIRST, fi_L);
    shiftOut(dataPin, clockPin, LSBFIRST, fi_H);
    shiftOut(dataPin, clockPin, LSBFIRST, matriz[i+1]);
    shiftOut(dataPin, clockPin, LSBFIRST, matriz[i]);
    digitalWrite(latchPin, 1);
    if (i<14){
      fi_L<<=1;
      bitClear(fi_L,0);
    }
    else if (i==14){
      fi_L=0x00;
      fi_H=0x01;
    }
    else{
      fi_H<<=1;
      bitClear(fi_H,0);
    }
    delay(250);
  }
}

viernes, 17 de enero de 2014

arduinoframeanimator.jar

en cuanto consiga decodificar la matriz que genera, lo pondré.

barrido de la matriz (74HC595)

Tiene un pequeño retardo. Se muestran los 32 primeros números expresados en binario 0-31)
código:
//salidas que se van a utilizar
byte latchPin = 8;
byte clockPin = 12;
byte dataPin = 11;
//array en el que se va a contener toda la informacion de filas
byte dato[32];//informacion de las filas
byte i;
byte co_L, co_H;

void setup() {
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  for (i=0;i<32;i++) {
    dato[i]=i;
  }
}

void loop() {
  muestra (dato);
}

void muestra (byte *matriz) {
  co_L=0xFE;
  co_H=0xFF;
  for (i=0;i<16;i++) {
    digitalWrite(latchPin, 0);
    shiftOut(dataPin, clockPin, MSBFIRST, matriz[i+16]);
    shiftOut(dataPin, clockPin, MSBFIRST, matriz[i]);
    shiftOut(dataPin, clockPin, MSBFIRST, co_H);
    shiftOut(dataPin, clockPin, MSBFIRST, co_L);
    digitalWrite(latchPin, 1);
    if (i<8){
      co_L<<=1;
      bitSet(co_L,0);
    }
    else{
      co_H<<=1;
      bitSet(co_H,0);
    }
    if (i==7){
      co_L=0xFF;
      co_H=0xFE;
    }
    delay(5);
  }
}

jueves, 16 de enero de 2014

instalación del programador

La versión que viene por defecto en ubuntu es muy antigua y no tiene al leonardo.
Por suerte está hecho en java y basta con descargarlo y ejecutar el fichero arduino que es un script escrito para /bin/sh y no tiene ninguna complicación.

La versión 1.0.5 funciona.
Me llevó un tiempo descubrir que los menús están ocultos en la parte superior de color gris oscuro (no se ven las letras porque deben haberlas configurado del mismo color) encima de la verde que contiene los iconos.
Para seleccionar el leonardo:

  • Herramientas -> Tarjetas -> Arduino Leonardo.
  • Herramientas -> Puerto Serial -> /dev/ttyACM1 (es necesario que esté conectado)

Control de una matriz led de 16x16 y por extensión a todas (74HC595)

Hay poca información en la web y esa poca cuesta aplicarla a un caso concreto.
El principal detalle es: 74hc595 driver.
Se trata de registros de desplazamiento. En este caso dos de 8 para las filas y 2 de 8 para las columnas.

Pongo códigos que es la forma más sencilla de entenderlos.
Código 1:
//salidas que se van a utilizar
int latchPin = 8;
int clockPin = 12;
int dataPin = 11;
//array en el que se va a contener toda la informacin de filas y columnas
byte dato[4];
//i va a variar de 0 a 7 por eso es suficiente con un byte
byte i;

void setup() {
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  dato[0]=0xFF;//columna mayor peso
  dato[1]=0xFF;//columna menor peso
  dato[2]=0x00;//fila mayor peso
  dato[3]=0x00;//fila menor peso
  envia_datos(dato);
}

/****************************************************************
 * bitWrite()
 * Descripción
 * Escribe un bit de una variable numérica.
 * Sintaxis
 * bitWrite(x, n, b)
 * Parámetros
 * x: la variable numérica en la que vamos a escribir
 * n: en cual de los bits vamos a escribir, empezando en el 0 para el bit menos significativo (el que está más a la derecha)
 * b: el valor a escribir en el bit (0 o 1)
 * 
 * bitRead()
 * Descripción
 * Lee un bit de un número.
 * Sintaxis
 * bitRead(x, n)
 * Parámetros
 * x: el número en el que queremos leer
 * n: cual de los bits queremos leer, empezando por el 0 para el bit menos significativo (el que está más a la derecha)
 * Devuelve
 * el valor del bit (0 o 1). 
 * 
 * bitSet()
 * Descripción
 * Pone a uno un bit de una variable numérica.
 * Sintaxis
 * bitSet(x, n)
 * Parámetros
 * x: la variable numérica en la que está el bit a poner a uno
 * n: cual de los bits queremos poner a uno, empezando en el 0 para el bit menos significativo (el que está más a la derecha) 
 * 
 * bitClear()
 * Descripción
 * Limpia (pone a cero) un bit de una variable numérica.
 * Sintaxis
 * bitClear(x, n)
 * Parámetros
 * x: la variable numérica con el bit a limpiar
 * n: cual de los bits queremos limpiar, empezando en el 0 por el bit menos significativo (el que está más a la derecha) 
 ***************************************************************/

void envia_datos(byte *matrix) {
  digitalWrite(latchPin, 0);
  for (byte i=4; i>2; i--) shiftOut(dataPin, clockPin, LSBFIRST, matrix[i-1]);
  for (byte i=2; i>0; i--) shiftOut(dataPin, clockPin, MSBFIRST, matrix[i-1]);
  digitalWrite(latchPin, 1);
  delay(500);
}

void loop() {
  for (i=0;i<8;i++) {
    dato[2]<<=1;
    bitSet(dato[2], 0);
    envia_datos(dato);

    dato[1]<<=1;
    bitClear(dato[1],0);
    envia_datos(dato);

    dato[3]>>=1;
    bitSet(dato[3],7);
    envia_datos(dato);

    dato[0]>>=1;
    bitClear(dato[0],7);
    envia_datos(dato);
  }//2130
  for (i=0;i<8;i++) {
    dato[2]>>=1;
    bitClear(dato[2],7);
    envia_datos(dato);

    dato[1]>>=1;
    bitSet(dato[1],7);
    envia_datos(dato);

    dato[3]<<=1;
    bitClear(dato[3], 0);
    envia_datos(dato);
    
    dato[0]<<=1;
    bitSet(dato[0],0);
    envia_datos(dato);
  }  

}
Código 2: Para ver cuales son las filas, las columnas, ánodos, cátodos, mayores y menores pesos.
//salidas que se van a utilizar
int latchPin = 8;
int clockPin = 12;
int dataPin = 11;
byte dato[4];
void setup() {
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
}
void envia_datos(byte *matrix) {
  digitalWrite(latchPin, 0);
  for (byte i=4; i>2; i--) shiftOut(dataPin, clockPin, LSBFIRST, matrix[i-1]);
  for (byte i=2; i>0; i--) shiftOut(dataPin, clockPin, MSBFIRST, matrix[i-1]);
  digitalWrite(latchPin, 1);
}
void loop() {
  //FILAS
  dato[3]=0x01; //anodo menor peso
  dato[2]=0xA0; //anodo mayor peso
  //COLUMNAS
  dato[1]=0x0F; //catodo mayor peso
  dato[0]=0x73; //catodo menor peso
  envia_datos(dato); //fila (vertical)-anodo 1000 0000 - 0000 0101 + columna (vertical) catodo 11111 0000 - 1100 1110
  /*dato[1]  dato[0]
    F    0    3    7
  0000 1111 0011 0001
  0000 0000 0000 0000
  0000 1111 0011 0001 A
  0000 0000 0000 0000
                      dato[3]
  0000 0000 0000 0000
  0000 0000 0000 0000
  0000 0000 0000 0000 0
  0000 0000 0000 0000
  
  0000 0000 0000 0000
  0000 0000 0000 0000
  0000 0000 0000 0000 0
  0000 0000 0000 0000
                      dato[2]
  0000 0000 0000 0000
  0000 0000 0000 0000
  0000 0000 0000 0000 1
  0000 1111 0011 0001
  */
  delay(100000);//para no hacer uso innecesario de la CPU
}