Go Down

Topic: Multiplexar datos que vienen de varias placas de Arduino. (Read 2326 times) previous topic - next topic

Gastonc4

Hola,

Estuve probando la librería SevenSeg y me fue muy bien, leyendo un poco la guía encontré la forma de controlar los displays de forma separada y de configurar si es cátodo o ánodo común.

Los displays se ven más estables, por ahora estoy trabajando con 2 sensores para entender un poco mejor la librería y sucede que cuando los 2 espacios están desocupados o llenos, los displays salen correctamente, pero cuando hay uno lleno y otro desocupado empieza a parpadear con un pulso de unos 100 milisegundos cada un segundo aproximadamente. Al parecer el código está bien, pruebo las lecturas de los pines digitales de forma manual y sale todo bien.

Creo que la opción de un solo pulso para todos los sensores debe generar algún tipo de error o inestabilidad, voy a probar usando pulsos para cada sensor a ver como me va, lo malo es que usaría muchos pines y no van a alcanzarme, tocará usar la opción de los registros de desplazamiento para reducir pines.

Cualquier sugerencia o idea será bienvenida, gracias a este foro he ido superando situaciones poco a poco.

surbyte

Quote
sucede que cuando los 2 espacios están desocupados o llenos, los displays salen correctamente, pero cuando hay uno lleno y otro desocupado empieza a parpadear con un pulso de unos 100 milisegundos cada un segundo
No te comprendo.

dos espacios desocupados? Cuales espacios?

Gastonc4

Ahhh disculpa, lo que pasa es que tengo el proyecto montado en protoboard a escala, cuando digo espacios desocupados o llenos, me refiero a que es como si un carro estuviese parqueado (lleno) o está disponible, recuerda que es un parqueadero,  claro que realmente lo que hago es acercar un objeto al sensor para indicar que está lleno ese espacio.

Gastonc4

Hola,

Después de varias semanas de investigación y solucionando situaciones que se han presentado a lo largo de este proyecto, he ido ordenando todo y llegando a conclusiones.

La parte de los sensores se encuentra aparentemente solucionada, me toca usar muchos pines de esta forma he obtenido los mejores resultados, utilizo 2 pines por cada sensor, serìan 24, pero es un Arduino Mega y puedo usar mas pines.

La parte de los displays utilizo dos 74HC595 y una librería llamada TimerOne, esto lo saque de un tutorial en la web donde utilizo 5 pines y puedo utilizar hasta 8 displays.

Para los leds estoy utilizando también el 74HC595, tanto para los rojos como para los verdes, pero aquí me encuentro con la situación de hasta ahora he podido controlar 8 leds que son las salidas del primer registro de desplazamiento, para esto uso valores decimales para representar cada led, por lo menos, para encender el primer led coloco el número 1, para el segundo el número 2, para el tercero el 4, y asì sucesivamente hasta el octavo que serìa el valor de 128.

Algo así:
Code: [Select]

  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, MSBFIRST, 128); 
  digitalWrite(latchPin, HIGH);


El problema se me presenta al encender los 8 leds del siguiente registro, he hecho las conexiones como aparece en la mayoría de los tutoriales( el pin 9 del primero(Q7') al pin 14 del segundo(DS)), los SH y ST en paralelo con los pines del Arduino, OE a gnd y MR a VCC y según mi instinto debería vebir el valor de 256 para que se encienda el primer led del segundo registro, pero no sucede, pero si enciende cuando enciende el primer led del primer registro.

He buscado en la web y no he encontrado un código que se asemeje a lo que necesito, los que encuentro son de efectos varios, secuencias y cosas por el estilo que son muy avanzados para mi.

Sólo necesito saber como activar el segundo registro ya que necesitarìa en total 3 registros para completar los 24 leds que necesito controlar.

Voy a seguir buscando y probando hasta que pueda avanzar, cualquier aporte que puedan hacer será de gran ayuda.




surbyte

Hay muchos ejemplos de contadores de 4 y 5 digitos en hardware.
TE busco alguno para que veas. Es sumamente fácil de hacer con los 595.

Contador de 5 digitos

Gastonc4

Surbyte,

Lo de los displays ya lo tengo listo, lo que me falta es lo de los leds.

El segundo registro se comporta igual que el primero, como si estuvieran en paralelo, ya he revisado las conexiones, cambiado cables, dispositivos y nada que logro que encienda el segundo registro con el valor de 256. Cuando le le doy el valor de 1, entonces enciende el primer led del primer registro y el primer led del segundo registro tambièn.

Parece que los datos fueran iguales en los 2 registros, no pasan de 8 bits y no se comportan como una cascada.

Ahì es donde debo solucionar.


surbyte

No entiendo algo, dices que los displays funcionan y no funcionan los leds? Pero resulta que funcionalmente son lo mismo, por eso no comprendo.

Ya a esta altura necesiaría ver el programa completo, y un esquema de todo.. mas alla que digas esto esta conectado acá y lo otro allá.
Hay que ver como interactúa todo porque yo te dejé en la parte multiplexada pero ahora ya estamos en otra cosa y sumaste timerOne, displays, etc.

O minimamente hablemos de la situación de los leds que refieres pero entonces se especifico con un programa completo y un esquema para yo poder seguirte.

Gastonc4

Bueno, mas bien hablemos por ahora solo de los leds, estoy trabajando los códigos por partes y después los uniré.

El código que tengo para los leds funciona para los primeros 8 leds, pero como comenté, se encienden también los 8 que siguen como si estuvieran en paraleo.

Code: [Select]

int ocup=0;
int latchPin = 8;    //Pin conectado a ST_CP of 74HC595
int clockPin = 9;    //Pin conectado a SH_CP of 74HC595
int dataPin =  10;     //Pin connected to DS of 74HC595

void setup() {
   pinMode(latchPin, OUTPUT);
   pinMode(clockPin, OUTPUT);
   pinMode(dataPin, OUTPUT);
   pinMode(0, INPUT);
   pinMode(1, INPUT);
   pinMode(2, INPUT);
   pinMode(3, INPUT); 
   pinMode(4, INPUT);
   pinMode(5, INPUT);
   pinMode(6, INPUT);
   pinMode(7, INPUT);
   pinMode(A0,INPUT);
   pinMode(A1,INPUT);
   pinMode(A2,INPUT);
   pinMode(A3,INPUT);
   pinMode(A4,INPUT);
   pinMode(A5,INPUT);
   pinMode(11,INPUT);
   pinMode(12,INPUT);
 }

void loop() {
 if(digitalRead(0)==1){
   digitalWrite(latchPin,LOW);
   shiftOut(dataPin, clockPin, MSBFIRST, ocup+1);
   digitalWrite(latchPin, HIGH);
   }
 else{
   digitalWrite(latchPin,LOW);
   shiftOut(dataPin, clockPin, MSBFIRST, ocup);
   digitalWrite(latchPin, HIGH);
  }

if(digitalRead(1)==1){
   digitalWrite(latchPin,LOW);
   shiftOut(dataPin, clockPin, MSBFIRST, ocup+2);
   digitalWrite(latchPin, HIGH);
  }
 else{
   digitalWrite(latchPin,LOW);
   shiftOut(dataPin, clockPin, MSBFIRST, ocup);
   digitalWrite(latchPin, HIGH);
  }

if(digitalRead(2)==1){
   digitalWrite(latchPin,LOW);
   shiftOut(dataPin, clockPin, MSBFIRST, ocup+4);
   digitalWrite(latchPin, HIGH);
 }
 else{
   digitalWrite(latchPin,LOW);
   shiftOut(dataPin, clockPin, MSBFIRST, ocup);
   digitalWrite(latchPin, HIGH);
  }
 
  if(digitalRead(3)==1){
   digitalWrite(latchPin,LOW);
   shiftOut(dataPin, clockPin, MSBFIRST, ocup+8);
   digitalWrite(latchPin, HIGH);
  }
 else{
   digitalWrite(latchPin,LOW);
   shiftOut(dataPin, clockPin, MSBFIRST, ocup);
   digitalWrite(latchPin, HIGH);
  }

 if(digitalRead(4)==1){
   digitalWrite(latchPin,LOW);
   shiftOut(dataPin, clockPin, MSBFIRST, ocup+16);
   digitalWrite(latchPin, HIGH);
 }
 else{
   digitalWrite(latchPin,LOW);
   shiftOut(dataPin, clockPin, MSBFIRST, ocup);
   digitalWrite(latchPin, HIGH);
 }

 if(digitalRead(5)==1){
   digitalWrite(latchPin,LOW);
   shiftOut(dataPin, clockPin, MSBFIRST, ocup+32);
   digitalWrite(latchPin, HIGH);
 }
 else{
   digitalWrite(latchPin,LOW);
   shiftOut(dataPin, clockPin, MSBFIRST, ocup);
   digitalWrite(latchPin, HIGH);
 }

 if(digitalRead(6)==1){
   digitalWrite(latchPin,LOW);
   shiftOut(dataPin, clockPin, MSBFIRST, ocup+64);
   digitalWrite(latchPin, HIGH);
  }
 else{
   digitalWrite(latchPin,LOW);
   shiftOut(dataPin, clockPin, MSBFIRST, ocup);
   digitalWrite(latchPin, HIGH);
  }

 if(digitalRead(7)==1){
   digitalWrite(latchPin,LOW);
   shiftOut(dataPin, clockPin, MSBFIRST, ocup+128);
   digitalWrite(latchPin, HIGH);
 }
 else{
   digitalWrite(latchPin,LOW);
   shiftOut(dataPin, clockPin, MSBFIRST, ocup);
   digitalWrite(latchPin, HIGH);
  }
   
  if(digitalRead(A0)==1){
   digitalWrite(latchPin,LOW);
   shiftOut(dataPin, clockPin, MSBFIRST, ocup+256);
   digitalWrite(latchPin, HIGH);
 }
 else{
   digitalWrite(latchPin,LOW);
   shiftOut(dataPin, clockPin, MSBFIRST, ocup);
   digitalWrite(latchPin, HIGH);
 }
}


Cuando llega a esta parte no se eniende ningún led.
Code: [Select]

if(digitalRead(A0)==1){
   digitalWrite(latchPin,LOW);
   shiftOut(dataPin, clockPin, MSBFIRST, ocup+256);
   digitalWrite(latchPin, HIGH);
 }
 else{
   digitalWrite(latchPin,LOW);
   shiftOut(dataPin, clockPin, MSBFIRST, ocup);
   digitalWrite(latchPin, HIGH);


He visto en la web que hay que agregar una línea para mandar 16 bits, pero no se como, hago algunas modificaciones pero siempre se encienden 2 leds en paralelo.
La línea es algo así:
Code: [Select]

if(digitalRead(A0)==1){
   digitalWrite(latchPin,LOW);
   shiftOut(dataPin, clockPin, MSBFIRST, (256>>8));
   digitalWrite(latchPin, HIGH);

Pero no se cómo agregarla sin que afecte a los primeros 8 bits o si hy que agregarla desde el principio del void loop.

IgnoranteAbsoluto

Sólo necesito saber como activar el segundo registro ya que necesitarìa en total 3 registros para completar los 24 leds que necesito controlar.
Has de mandar los tres bytes seguidos, uno detrás de otro, y por último poner el latchPin a nivel alto. Dependiendo de qué registro quieras "mandar primero" los mandas en un orden u otro.
Code: [Select]
   digitalWrite(latchPin,LOW);
   shiftOut(dataPin, clockPin, MSBFIRST, registro1);
   shiftOut(dataPin, clockPin, MSBFIRST, registro2);
   shiftOut(dataPin, clockPin, MSBFIRST, registro3);
   digitalWrite(latchPin, HIGH);


O mandas primero el registro3:
Code: [Select]
   digitalWrite(latchPin,LOW);
   shiftOut(dataPin, clockPin, MSBFIRST, registro3);
   shiftOut(dataPin, clockPin, MSBFIRST, registro2);
   shiftOut(dataPin, clockPin, MSBFIRST, registro1);
   digitalWrite(latchPin, HIGH);


Ten en cuenta que cada "registro" es de tipo byte.

Para hacerlo con el ejemplo que has puesto, con la variable ocup de tipo int deberías de hacer:
Code: [Select]
   digitalWrite(latchPin,LOW);
   shiftOut(dataPin, clockPin, MSBFIRST, ocup >> 8);
   shiftOut(dataPin, clockPin, MSBFIRST, ocup);
   digitalWrite(latchPin, HIGH);


Esto mandaría primero el byte más significativo y después el menos significativo. Pero aún así tu código no funcionará como tú esperas porque no estás guardando los valores en la variable.

Yo haría el programa con dos arrays y tres bucles, pero para que te funcione lo que tienes y entiendas cómo funciona, debería de ser suficiente algo tal que así:

Code: [Select]
int ocup=0;
int latchPin = 8;    //Pin conectado a ST_CP of 74HC595
int clockPin = 9;    //Pin conectado a SH_CP of 74HC595
int dataPin =  10;     //Pin connected to DS of 74HC595

void setup() {
   pinMode(latchPin, OUTPUT);
   pinMode(clockPin, OUTPUT);
   pinMode(dataPin, OUTPUT);
   pinMode(0, INPUT);
   pinMode(1, INPUT);
   pinMode(2, INPUT);
   pinMode(3, INPUT); 
   pinMode(4, INPUT);
   pinMode(5, INPUT);
   pinMode(6, INPUT);
   pinMode(7, INPUT);
   pinMode(A0,INPUT);
   pinMode(A1,INPUT);
   pinMode(A2,INPUT);
   pinMode(A3,INPUT);
   pinMode(A4,INPUT);
   pinMode(A5,INPUT);
   pinMode(11,INPUT);
   pinMode(12,INPUT);
 }

void loop() {
    ocup = 0; // Ponemos a cero todos los bits
    if(digitalRead(0)) { // No hace falta más para saber que está a nivel alto
        ocup |= 1 << 0; // Ponemos a 1 el bit 0
    }
    if(digitalRead(1)) {
        ocup |= 1 << 1; // Ponemos a 1 el bit 1
    }
    if(digitalRead(2)) {
        ocup |= 1 << 2; // Ponemos a 1 el bit 2
    }
    if(digitalRead(3)) {
        ocup |= 1 << 3; // Ponemos a 1 el bit 3
    }
    if(digitalRead(4)) {
        ocup |= 1 << 4; // Ponemos a 1 el bit 4
    }
    if(digitalRead(5)) {
        ocup |= 1 << 5;
    }
    if(digitalRead(6)) {
        ocup |= 1 << 6;
    }
    if(digitalRead(7)) {
        ocup |= 1 << 7;
    }
    if(digitalRead(A0)) {
        ocup |= 1 << 8;
    }
    if(digitalRead(A1)) {
        ocup |= 1 << 9;
    }
    if(digitalRead(A2)) {
        ocup |= 1 << 10;
    }
    if(digitalRead(A3)) {
        ocup |= 1 << 11;
    }
    if(digitalRead(A4)) {
        ocup |= 1 << 12;
    }
    if(digitalRead(A5)) {
        ocup |= 1 << 13;
    }
    if(digitalRead(11)) {
        ocup |= 1 << 14;
    }
    if(digitalRead(12)) {
        ocup |= 1 << 15; // Un entero de 16 bits tiene 16 bits (del 0 al 15)
    }

    // A continuación se mandan los dos bytes del entero
    digitalWrite(latchPin,LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, ocup >> 8); // Primero el byte más significativo
    shiftOut(dataPin, clockPin, MSBFIRST, ocup);
    digitalWrite(latchPin, HIGH);
}


Aviso, no he probado el código ya que lo he escrito desde la tablet y ni tan siquiera garantizo que compile.

Y repito: lo he hecho así, siguiendo con tu ejemplo, para que te hagas una idea de cómo funciona "la cosa". Porque creo que se podría hacer más "compacto" el programa únicamente con dos arrays, tres for y un único if.





surbyte

Acá tienes algo que funciona.

Code: [Select]
const byte latchPin  = 8;    //Pin conectado a ST_CP of 74HC595
const byte clockPin  = 9;    //Pin conectado a SH_CP of 74HC595
const byte dataPin   = 10;     //Pin connected to DS of 74HC595

byte estadoLSB, estadoLSBAnt;
byte estadoMSB, estadoMSBAnt;

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

  DDRD = B00000000; // todas entradas
  DDRC = B11100000; // todas entradas
  DDRB = DDRB | B11100111;
 }

void loop() {

  estadoLSB = PIND;
  estadoMSB = PINC | (PINB & 0x18)<<3;
  
  if (estadoLSB != estadoLSBAnt)
      dato595(estadoLSB, estadoMSB);
  estadoLSBAnt = estadoLSB;

  if (estadoMSB != estadoMSBAnt)
      dato595(estadoLSB, estadoMSB);
  estadoMSBAnt = estadoMSB;

 
}

void dato595(byte tmp1, byte tmp2) {
    
  digitalWrite(latchPin,LOW);
  shiftOut(dataPin, clockPin, LSBFIRST, tmp1);
  shiftOut(dataPin, clockPin, LSBFIRST, tmp2);
  digitalWrite(latchPin, HIGH);
}


Lo que faltaba era enviar dos datos uno para el LSB y otro para el MSB
El método que estabas usando funciona pero se hacía muy tedioso por eso elegi manipulacion de PUERTOS.

DDRx es para asignar se usas entradas 0 o salidas 1
Donde veas un 0 es porque asigno entradas y donde veas un 1 es porque seran salidas.

PINx es para leer el puerto
el otro comando es PORTx que no lo uso

Tienes 2 o 3 partes mas o menos complicadas

1)  
Code: [Select]
estadoLSB = PIND;
Leo todo lo que va desde D0 a D7 o sea el puerto D por eso para leer uso PIND

2) cuando lees los pines del A0..A5 y luego le sumas D11 y D12 debo hacer manipulacion de bits para armar el otro byte

 
Code: [Select]
estadoMSB = PINC | (PINB & 0x18)<<3;

Resulta que D11 y D12 son los bits que estan en estas posiciones 00011000 esos dos en 1 son los bits D12 y D11 eso traducido en hexa es 0x18 por eso cuando leo PINB o sea ese puerto descarto todo poco tmb estas enviando datos por los shiftregisters y no se en que estado quedan
Asi que haciendo un AND con 0x18 solo me quedo con esos bits esten como esten segun la lectura
Luego a dichos pines debe agregarlos a los 6 bits leidos del puerto C o sea los A0 ... A5
por lo tanto debo moverlos 3 lugares para que se acomoden como si fueran 1 solo byte

Asi termino armando el 2do byte.

Finalmente hice un procedimiento que envia a los 595 primero el byte LSB y luego el MSB


IgnoranteAbsoluto

@Gastonc4 la solución que ha puesto @surbyte es la más compacta, rápida y eficiente posible. Compacta porque lo hace con pocas instrucciones y poca memoria. Rápida (calculo que al menos unas 300 veces más rápida) porque trabaja diréctamente con los registros que controla los pines, sin pasar por la función digitalRead() que es "relativamente lenta". Y eficiente, además de por lo ya dicho, porque no envía los datos constantemente si no ha habido cambios. Los manda sólo si es necesario.

Pero el precio que se ha pagar por tanta "velocidad" y eficiencia es lo difícilmente que resulta de mantener el código o portarlo a otro hardware. En el caso de querer cambiar el orden de asignación de los pines, o de querer otros pines, o de necesitar portarlo a otro tipo de Arduino (pongamos por ejemplo un Arduino Mega porque requerimos de más pines), es mucho más complejo de modificar el programa.

Por eso se suele usar la "lenta" función digitalRead() en lugar de acceder diréctamente a los registros que controlan los pines. A no ser que se requiera de mucha velocidad de acceso a ellos.

Repito, la propueta de @surbyte es la más eficiente. Sin embargo yo lo haría de una forma más fácilmente mantenible y portable ya que creo que no es necesario tanta velocidad y eficiencia.

IgnoranteAbsoluto

Code: [Select]
// Definición de los pines de entrada. Se pueden poner la cantidad y en el orden en que se quiera
const byte PINES_ENTRADAS[] = {0, 1, 2, 3, 4, 5, 6, 7, A0, A1, A2, A3, A4, A5, 11, 12};

// Pines destinado a controlar los 74HC595
const int LATCH_PIN = 8; // Pin conectado al ST_CP del 74HC595
const int CLOCK_PIN = 9; // Pin conectado al SH_CP del 74HC595
const int DATA_PIN = 10; // Pin conectado al DS del 74HC595

// Constantes que se calculan en función del tamaño del array PINES_ENTRADAS
const int CANTIDAD_ENTRADAS = sizeof(PINES_ENTRADAS) / sizeof(PINES_ENTRADAS[0]);
const int LONGITUD_BUFFER_595 = (CANTIDAD_ENTRADAS + 7) / 8;

byte buffer595[LONGITUD_BUFFER_595];

void setup() {
    pinMode(LATCH_PIN, OUTPUT);
    pinMode(CLOCK_PIN, OUTPUT);
    pinMode(DATA_PIN, OUTPUT);
    for (int i = 0; i < CANTIDAD_ENTRADAS; i++) { // Configura como entrada todos los pines definidos en PINES_ENTRADAS
        pinMode(PINES_ENTRADAS[i], INPUT);
    }
}

void loop() {
    memset(buffer595, 0, sizeof(buffer595)); // Pone a cero todos los bytes del buffer
    for (int i = 0; i < CANTIDAD_ENTRADAS; i++) { // Bucle para leer cada uno de los pines de entrada
        if (digitalRead(PINES_ENTRADAS[i])) { // No hace falta más para saber si está a nivel alto
            buffer595[i / 8] |= 1 << (i % 8); // En caso de estar a nivel alto, se pone a 1 el bit correspondiente en el buffer
        }
    }
    // A continuación se mandan todos los bytes
    digitalWrite(LATCH_PIN, LOW);
    for (int i = LONGITUD_BUFFER_595 - 1; i >= 0; i--) { // Bucle para mandar primero el "byte más significativo"
        shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, buffer595[i]);
    }
    digitalWrite(LATCH_PIN, HIGH);
}

/*
    for (int i = 0; i < LONGITUD_BUFFER_595; i++) { // Bucle para mandar primero el "byte menos significativo"
 */


Esta es mi propuesta "flexible". Para cambiar el número de pines de entrada o el orden en que se quieren, no hay más que modificar el array PINES_ENTRADAS. El resto del programa "se ajusta" al compilar.

La idea base es que, en lugar de tener líneas de código dedicadas a tratar únicamente una entrada y repetir esas líneas con ligeros cambios para cada una de las entradas, se tratan todas las entradas por igual y con el mismo código. Para ello se define el array PINES_ENTRADAS en donde se guardan los pines que se desean y en el orden que se quiera.

Por otro lado, en lugar de definir una, dos, tres o las variables que sean necesarias (registro1, registro2...) para guardar la información que se tiene que enviar a los 74HC595 en función de la cantidad de 74HC595 que se necesiten, lo que se hace es definir el array buffer595 con el tamaño adecuado para guardar todos los bytes que se necesiten en función del número de pines que se definen en el array PINES_ENTRADAS. Por ejemplo: si se definen 8 pines se necesita 1 byte (y un 74HC595). Si se definen 17 pines se necesitan 3 bytes (y tres 74HC595). Es por esto que el tamaño del buffer se calcula como el resultado de la división entera del número de pines más 7 entre 8. El sumarle 7 es por si el número de pines no es múltiplo de 8.

Al principio del loop() se ponen a cero todo los bits del buffer. Se hace un barrido de todas las entradas y se pone a uno su correspondiente bit en el buffer si la entrada está a nivel alto. Finalmente se envía la información del buffer a los 74HC595.

El bucle que envía los bytes lo hace mandando primero los "más significativos" ya que he visto que originalmente se invocaba shiftOut() con el parámetro MSBFIRST indicando con ello que se quería que se mandara primero el bit más significativo de cada byte enviado. Si se desea que los bytes se envíen en el orden contrario basta con cambiar el for...
Code: [Select]
for (int i = LONGITUD_BUFFER_595 - 1; i >= 0; i--) {
... por el for que se encuentra comentado al final del código...
Code: [Select]
for (int i = 0; i < LONGITUD_BUFFER_595; i++) {
Cuidado con el i-- que pasa a ser i++ si se hace el cambio "a mano" en lugar de "copiar y pegar".


Esta versión envía continuamente la información a los 74HC595 aunque no hubiesen cambios. Se pueden hacer un par de modificaciones para que no se reenvíen los datos si ningún bit ha cambiado desde la última vez que se han mandado a los 74HC595.

El código no lo he probado ya que no tengo el hardware necesario para ello. Sólo he verificado que compila sin errores.

Gastonc4

Hola amigos

@surbyte e @IgnoranteAbsoluto (que por cierto no concuerda el nick con tu conocimiento, jajaja), primero que todo muchas gracias por estar al tanto de este proyecto, sus ideas son muy buenas y claro que intentaré resolver la situación por estos métodos. hasta ahora los proyectos que he realizado en Arduino son de códigos mucho màs sencillos donde hago secuencia de luces y una que otra comunicaciòn por bluetooth. Para mi todas estas cosas son un poco avanzadas ya que no soy programador ni tengo mucha idea de sistemas, pero si manejo la parte electrónica.

Claro, eso no quiere decir que me rinda tan fácil, me gustan los retos y al final de todo, esto valdrá la pena.
Voy a ir probando y tratando de entender un poco más ya que este proyecto sera montado con un arduino Mega y aparte de los leds que en este caso serían rojos, que me indican los puestos ocupados del parqueadero, tambièn necesito implementar leds de color verde que me indicarán los puestos disponibles, pero ya entendiendo un poco más el código creo que puedo hacerlo.

Luego de ir superando esta parte, tengo que enviar los datos a un servidor por medio de la shield ethernet W5100, pero de eso hablaré después, por lo pronto ya superamos la lectura de los sensores ultrasónicos, el multiplexado de los displays 7 segmentos y ahora lo de los leds que va tomando buen camino, recuerden que son 24 leds, pero ya sabiendo mandar los 16 bits, no creo que cueste mucho enviar los otros 8 bits.

Apenas haga las respectivas pruebas me comunicaré y les diré como voy, por lo pronto me queda decirles muchas gracias de nuevo...

Gastonc4

Hola amigos,

Probando todos los códigos, funcionan hasta los 16 bits.

Estoy ahora trabajando con un arduino Mega, para poder utilizar mas pines de entrada y teniendo en cuenta que al final, esta es la tarjeta que usaré, ya que con el arduino uno no me alcanzan para las 24 entradas. Modificando un poco por mi cuenta el primer código de @IgnoranteAbsoluto para lograr los 24 bits, cambio la variable ocup que es de tipo int, por tipo long y después por tipo unsigned long y agragado el otro registro, no me funciona, no se que hago mal, sólo sigo el patrón que lleva.

el código que así:


Code: [Select]
unsigned long ocup=0;
unsigned long latchPin = 53;    //Pin conectado a ST_CP of 74HC595
unsigned long clockPin = 51;    //Pin conectado a SH_CP of 74HC595
unsigned long dataPin =  52;     //Pin connected to DS of 74HC595

void setup() {
   pinMode(latchPin, OUTPUT);
   pinMode(clockPin, OUTPUT);
   pinMode(dataPin, OUTPUT);
   pinMode(1, INPUT);
   pinMode(3, INPUT);
   pinMode(5, INPUT);
   pinMode(7, INPUT);
   pinMode(9, INPUT);
   pinMode(11, INPUT);
   pinMode(13, INPUT);
   pinMode(15, INPUT);
   pinMode(17, INPUT);
   pinMode(19, INPUT);
   pinMode(21, INPUT);
   pinMode(23, INPUT);
   pinMode(25, INPUT);
   pinMode(29, INPUT);
   pinMode(31, INPUT);
   pinMode(33, INPUT);
   pinMode(35, INPUT);
   pinMode(37, INPUT);
   pinMode(39, INPUT);
   pinMode(41, INPUT);
   pinMode(43, INPUT);
   pinMode(45, INPUT);
 }

void loop() {
    ocup = 0; // Ponemos a cero todos los bits
    if(digitalRead(1)) { // No hace falta más para saber que está a nivel alto
        ocup |= 1 << 0; // Ponemos a 1 el bit 0
    }
    if(digitalRead(3)) {
        ocup |= 1 << 1; // Ponemos a 1 el bit 1
    }
    if(digitalRead(5)) {
        ocup |= 1 << 2; // Ponemos a 1 el bit 2
    }
    if(digitalRead(7)) {
        ocup |= 1 << 3; // Ponemos a 1 el bit 3
    }
    if(digitalRead(9)) {
        ocup |= 1 << 4; // Ponemos a 1 el bit 4
    }
    if(digitalRead(11)) {
        ocup |= 1 << 5;
    }
    if(digitalRead(13)) {
        ocup |= 1 << 6;
    }
    if(digitalRead(15)) {
        ocup |= 1 << 7;
    }
    if(digitalRead(17)) {
        ocup |= 1 << 8;
    }
    if(digitalRead(19)) {
        ocup |= 1 << 9;
    }
    if(digitalRead(21)) {
        ocup |= 1 << 10;
    }
    if(digitalRead(23)) {
        ocup |= 1 << 11;
    }
    if(digitalRead(25)) {
        ocup |= 1 << 12;
    }
    if(digitalRead(27)) {
        ocup |= 1 << 13;
    }
    if(digitalRead(29)) {
        ocup |= 1 << 14;
    }
    if(digitalRead(31)) {
        ocup |= 1 << 15; // Un entero de 16 bits tiene 16 bits (del 0 al 15)
    }
    if(digitalRead(33)) {
        ocup |= 1 << 16;
    }
    if(digitalRead(35)) {
        ocup |= 1 << 17;
    }
    if(digitalRead(37)) {
        ocup |= 1 << 18;
    }
    if(digitalRead(39)) {
        ocup |= 1 << 19;
    }
    if(digitalRead(41)) {
        ocup |= 1 << 20;
    }
     if(digitalRead(43)) {
        ocup |= 1 << 21;
    }
     if(digitalRead(45)) {
        ocup |= 1 << 22;
    }
     if(digitalRead(47)) {
        ocup |= 1 << 23;
    }

    // A continuación se mandan los dos bytes del entero
    digitalWrite(latchPin,LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, ocup >> 16);
    shiftOut(dataPin, clockPin, MSBFIRST, ocup >> 8); // Primero el byte más significativo
    shiftOut(dataPin, clockPin, MSBFIRST, ocup);
    digitalWrite(latchPin, HIGH);
}


Probé varias combinaciones en las variables, int, long, unsigned long, long long, pero nada que funciona.

Opto por esta opción debido a que no voy a hacer lectura de los pines sino lectura de los sensores ultrasónicos, en este caso sólo tengo que modificar la función if (digitalread(x)) por if (distanciax<300) y teniendo en cuenta las distancias es que voy a encender los leds, para mi es más fácil de este modo.

Así sería la lectura de un sensor:

Code: [Select]
void loop() {
  digitalWrite(0, LOW);
  delayMicroseconds(2);
  digitalWrite(0, HIGH); // genera el pulso de 10 us
  delayMicroseconds(10);
  digitalWrite(0, LOW);

  duracion1 = pulseIn(1, HIGH); // capturamos la duración del pulso
  distancia1 = (duracion1/2)/29; // calcula la distancia en cms

  if (distancia1 >=1 && distancia1 <=299){
     digitalWrite(latchPin,LOW);
     shiftOut(dataPin, clockPin, MSBFIRST, ocup+1);
     digitalWrite(latchPin, HIGH);
      }


Por eso es que me guío más por el primer código.

Probando el segundo código, fue fácil logar controlar los 24 bits, sólo tuve que agregar los pines de entrada en el array PINES_ENTRADA[] y listo, agregué el otro 74595 y los leds en el circuito, funcionó.
Pero ahora viene un pequeño detalle para mi, ¿es posible modificar esa parte para que sea un array de la lectura de los sensores? No tengo mucha idea de como hacer arrays, es por eso que los códigos me quedan un poco largos, pero así los entiendo, de todos modos la idea es ir aprendiendo.
Por ahora tengo los códigos y las simulaciones por separado, creo que ya es hora de irlos uniendo para darle la forma final al proyecto y saber si funciona todo.
Quedo atento a cualquier sugerencia.

surbyte

Tu problema esta aca

Code: [Select]
  // A continuación se mandan los dos bytes del entero
    digitalWrite(pinLatch,LOW);
    shiftOut(pinDatos, pinReloj, MSBFIRST, (ocup & 0x00ff0000) >> 16);
    shiftOut(pinDatos, pinReloj, MSBFIRST, (ocup & 0x0000ff00) >> 8); // Primero el byte más significativo
    shiftOut(pinDatos, pinReloj, MSBFIRST, (ocup & 0x000000ff));
    digitalWrite(pinLatch, HIGH);
}



Otro error menor es este

Code: [Select]
unsigned long ocup=0;            // <== definela como usnigned int o sea 32 bits porque necesitas 24 bits
const byte latchPin = 53;    //Pin conectado a ST_CP of 74HC595
const byte clockPin = 51;    //Pin conectado a SH_CP of 74HC595
const byte dataPin =  52;     //Pin connected to DS of 74HC595


Los pines debes ser como máximo int aunque es un desperdicio.
Lo mejor es const byte


Por ultiimo un detalle no por menos importante. El compilador si no le dices nada asume operaciones enteras o sea.. para el no existen las operaciones de 32 bits a menos que le indiques.

Desde aca debes agregar el el typecase

Code: [Select]
if(digitalRead(31)) {
        ocup |= (unsigned long) 1 << 15; // Un entero de 16 bits tiene 16 bits (del 0 al 15)
    }
    if(digitalRead(33)) {
        ocup |= (unsigned long) 1 << 16;
    }
    if(digitalRead(35)) {
        ocup |= (unsigned long) 1 << 17;
    }
    if(digitalRead(37)) {
        ocup |= (unsigned long) 1 << 18;
    }
    if(digitalRead(39)) {
        ocup |= (unsigned long) 1 << 19;
    }
    if(digitalRead(41)) {
        ocup |= (unsigned long) 1 << 20;
    }
     if(digitalRead(43)) {
        ocup |= (unsigned long) 1 << 21;
    }
     if(digitalRead(45)) {
        ocup |= (unsigned long) 1 << 22;
    }
     if(digitalRead(47)) {
        ocup |= (unsigned long) 1 << 23;
    }

Go Up