Arduino Forum

International => Español => Hardware => Topic started by: Gastonc4 on Aug 03, 2018, 09:39 pm

Title: Multiplexar datos que vienen de varias placas de Arduino.
Post by: Gastonc4 on Aug 03, 2018, 09:39 pm
Muy buenas a todos.

Tengo la misión de hacer un parqueadero con sensores que indique puestos disponibles y ocupados mediante leds, rojo (ocupado), verde (disponible). A eso no le veo dificultad, para eso utilizaré sensores ultrasónicos y placas de Arduino Mega, ya tengo un código que me ejecuta esa función. Lo que veo un poco complicado para mi es la cantidad de puestos deben aparecer en una pantalla de led 7 segmentos, una para ocupado y disponibles respectivamente, estamos hablando de 47 puestos pero divididos en 2 secciones, una de 23 y otra de 24,

Para esto cuento con 4 placas de Arduino Mega. Ya he logrado realizar para 12 puestos y el conteo de ocupados y disponibles por monitor serial, pero los pines de la placa no van a alcanzarme y tendré que usar otra placa, cosa que no le veo problema si el caso fuera sólo la indicación de los leds rojos y verdes, pero recuerden que esa informaón tengo que plasmarla en la pantalla de leds 7 segmentos.

Ya teniendo una idea de lo que tengo que hacer me surgen varias preguntas, ¿Hay forma de colocar a trabajar varias placas que sean los que me tomen la lectura de los sensores y esta lectura mandarla a otra placa que toma las variables, las sume y pueda hacer el multiplexado para refejar la lectura en la pantalla led?

Si pudieran decirme por donde debería empezar, se los agradecería. Espero haber sido claro en el detalle de todo lo que debo hacer en este proyecto.

De antemano, gracias por tomarse el tiempo de leer estas líneas.
Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: surbyte on Aug 03, 2018, 10:04 pm
Quote
Lo que veo un poco complicado para mi es la cantidad de puestos deben aparecer en una pantalla de led 7 segmentos, una para ocupado y disponibles respectivamente, estamos hablando de 47 puestos pero divididos en 2 secciones, una de 23 y otra de 24,
Entonces cuantos displays necesitas ser mostrados?

Reevaluemos el tema porque hay forma de hacerlo sin usar tantos MEGAS, aunque claro esa es una alternativa.

Por favor, si específico.. en que ocupas los pines.
Si vas a usar 23 y 24 leds dije LEDS no display de 7 segmentos tienes alterntivas tambien.
Si vas necesitar varios Displays 7 Segmentos pero que mostrarán que?
Todos lo mismo, o información relevante a cada grupo?
Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: Gastonc4 on Aug 04, 2018, 06:05 am
Hola Surbyte,

Gracias por dedicar un poco de tu tiempo a esta situación.

Voy a tratar de ser lo más específico posible.

Empezando por los displays, son 2 de 4 dígitos (2 pares), cada uno con la información de disponibles y ocupados de cada lado. El parqueadero cuando entras debes elegir un lado para estacionarte, el izquierdo que tiene 24 puestos o  el derecho que tiene 23, por eso lo de los 2 displays, Ej:  

        Lado Izquierdo                                      Lado Derecho
Disponibles          Ocupados                 Disponibles             Ocupados
     10                      14                            12                       11

Lo de los leds, estoy usando los sensores ultrasónicos, cuando se estaciona el auto se enciende un led rojo y si está disponible se enciende un led verde. Empezé usando los pines 2, 3, 4 y 5. El pin 2 para el Trigger, el 3 para el Echo, 4 para el led verde y 5 para el led rojo. Los enciendo mediante la función IF, dependiendo de la distancia captada por el sensor:

Code: [Select]
if (distancia1 >=1 && distancia1 <=150){
   digitalWrite(4, LOW);} // se enciende el led verde
   else{
    digitalWrite(4, HIGH);
}

 if (distancia1 >=151 && distancia1 <=499){
   digitalWrite(5, LOW);} // se enciende el led rojo
   else{
    digitalWrite(5, HIGH);
}


Cómo estoy usando led RGB de ánodo común envío un 0 cuando se estaciona el auto.

Y así sigo usando los pines siguientes bajo el mismo principio, pero si no estoy mal me alcanza una Mega para 15 ó 16 sensores, no me alcanzan los 23 sensores de uno de los lados y ahí es donde pregunto, ¿Que debo hacer para que me alcance una Mega para todos los sensores? o ¿Se puede conectar otra Mega para los sensores que faltan?
Para el asunto de los leds puedo usar otra Mega y la manejaría independiente de la otra, pero el asunto es que esos datos deben llegar a los displays, osea que necesitaría como ampliar los pines de una Mega usando la otra como si se fusionaran, espero hacerme entender.



Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: surbyte on Aug 04, 2018, 06:50 am
Bien ahora mucho mejor.
Lo unico que no has dicho es si para manejar esos displays empleas 7 + 4 + 4 o usas alguno especial como un MAX7219.

Evidentemente desconoces de algunos elementos que simplifican las cosas.
Mira esto, si usas un MAX7219 o 2 (1 x grupo) ya bajas las conexiones a 3 pines nada mas para los dos displays. Luego hablamos del software.
Los leds mismo truco pero usando los 74HC595 que manejan 8 salidas cada uno asi que necesitas para 23+24 = 47 salidas x 2 = 94 salidas / 8 = 12 integrados que totalizarían 96 posibles salidas.
Hasta aca llevamos 3 para displays mas 3 mas para estos leds, los 94 leds.

Nos faltan los sensores ultrasónicos.

Acá necesitamos 2 pines x sensor, pero en realidad se pueden hacer 2 cosas interesantes:
1. Que todos los pines de salida que emiten el pulso sean el mismo lo que reduce a 47 lecturas digitales o
2. Puedes usar multixplexores analógicos como el 4052 eligiendo que sensor vas a leer

Exsiten otras variantes x ejemplo con el 4051

O sea que de este modo necesitas 48/4 = 12 integrados y 24 pines digitales para esos 12 integrados mas 2 pines extra para decodificar que llave analógica usarás.

En conclusión...

2 + 1 (ChipSelect MAX7219) + 1 (ChipSelect diferente para los 595) +12 + 2 pines digitales = 18 pines digitales si no me olvido de algo.

Podrias usar un NANO/UNO o bien un Mega.

1 o 2 MAX7219 (http://www.avrprojects.net/images/led_driver_max7219_clock_sch.jpg)
12 74hc595 (https://www.nutsvolts.com/uploads/wygwam/NV_1110_Pardue_Figure-7---Serial-In-Parallel-Out-Schematic.jpg)
12 CD4052

Puede haber algun error porque no he verificado lo dicho, pero rondará estos números.

Solo son ideas, tambien puedes hacerlo con varios Arduinos pero no en serie. Salvo que un MEGA con 4 puertos se comunique con 4 Megas si hiciera falta.
Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: Gastonc4 on Aug 05, 2018, 12:53 am
Bueno, esto se pone interesante cada vez más.

Te cuento, por ahora el proyecto va a realizarse en las 2 partes, izquierda y derecha, es decir, hablemos de 24 leds y 24 sensores inicialmente, que sería el lado izquierdo   vamos a trabajarlos de forma independiente y el lado derecho sería una copia exacta del otro circuito y todo lo demás. Lo trabajaré así por solicitud del dueño del sitio y la verdad me parece más fácil así por cuestiones de distancias entre los 2 lados.

Físicamente tengo 4 arduino Mega, los sensores y los leds, lo demás es casi imposible conseguirlos en mi ciudad, dado el caso tocará pedirlos desde la capital.

La idea de simplificar las cosas me parece excelente, así se facilita todo, creo que por ahora la opción sería simplificar los leds con el 74HC595, los display inicialmente con 7 + 4 y usar en los sensores el mismo pulso de salida, voy a experimentar a ver como me va, ya que es fin de semana y no hay comercio funcionando.

Claro, nesecitaría una idea del código, ¿Cómo hago para usar el mismo pulso de salida para todos los sensores ultrasónicos?  ¿Simplemente se toma ese pin de salida y se coloca en paralelo con los demás o hay otra opción?

Iré trabajando y a medida que vaya avanzando comentaré como voy, quiero estar seguro que así como voy alcancen los pines para los 24 puestos iniciales, estaré atento a toda sugerencia.

Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: surbyte on Aug 06, 2018, 12:50 am
Vamos a desarrollar la idea del multiplexor.

Tienes dos opciones válidas :
1. puedes usar el CD4051 que es un multiplexor de 1 a 8
2. o el 4052 que es 2 a 4. Te expliqué el 2 a 4.

Ahora vamos con el 4051 1 a 8.

Tienes 1 pin bidireccional que puede direccionarse a 8 pines o a la inversa.

Estos son los pines de un HC SR04
 5V Supply
 Trigger Pulse Input
 Echo Pulse Output
 0V Ground

Entonces supongamos que como dices 24 sensores. Podrias usar 3 CD 4051 que van a direccionar el pin Trigger de cada sensor Ultrasónico. Y el pin Echo será común a un pin de modo que como son 24 veremos que consumo tiene eso para el pin Arduino.

El único problema que veo es que el sensor tiene un ángulo de 15 y que debes evitar que el mismo puso disparado en los 24 sensores genere un echo residual en algun sensor. 
Bueno en este punto me doy cuenta que la idea presenta problemas posibles como perder pulsos muy próximos.
Y si lo haces barriendo o sea que cada vez que quieras medir una distancia deberás disparar su trigger.
Asi que olvidemos x ahora la opción de un solo pulso de disparo. Y Tendremosque considerar que tenemos 2 pines multiplexados para cada sensor.

NUEVA IDEA!!!
Hay una técnica muy interesante que usa diodos para separar el uso de multiples botones/pulsadores y acá podriamos usar lo mismo. Un diodo 1n4148 o 1n914 sale de cada ECHO de los HC-SR04 y se unen en sus cátodos y requerirán una R de 10k a GND.
Ese punto común va a una interrupción del Arduino pin2 o 3 son las disponibles. En teoría entonces un pulso dispara a todos los sensores y el que vaya respondiendo dará su respuesta o se acumula en un array.
Hay que probar la idea.

Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: Gastonc4 on Aug 13, 2018, 06:44 pm
Hola,

Después de una semana de probar varias cosas he adelantado el proyecto basándome en tus ideas.
Coloqué en los trigger los cátodos de los diodos 1N4148 y en el punto común una resistencia de 10K a gnd y funciona muy bien, así utilizo un sólo pulso para todos los sensores reduciendo los pines a 24.
Lo de los leds opté por usar una sóla salida pero no usando leds RGB sino de los normales en paralelo pero invirtiendo su polaridad, cada uno con su resistencia, uno va a gnd y el otro a 5V, así cuando tengo un = en la salida se prende el led verde y cuando tengo un 1 se prende el led rojo, reduciendo los pines a 24, mas los 24 de los triggers, tengo 48 pines hasta ahora.
Claro, debo aclarar que sólo llevo conectado en la protoboard sólo 4 sensores y los 8 leds.

Lo del multiplexado ya lo empezé, he tomado un código y lo he ido modificando hasta lograr que me muestyre los datos, por ahora los display los muestran, pero empiezo con un delay de 1000 y se ven bien, claro uno por uno, pero a medida que voy reduciendo el delay, sólo uno de los disolays me queda con una intensidad buena y no parpadea, los demás si.

Quiero aclarar, no soy muy experto en el tema de la programación, pero poco a poco voy entrando en esto, creo que ese es el único detalle que debo resolver, por lo demás pieso que todo está bien.

Hasta ahora uso del pin 2 al 10, para los sensores y los leds.
Los pines desde el 43 hasta el 53 para el multiplexado.
Pines 50 al 53 para los transistores de los comunes de los displays.

Este es el código que usé, como lo dije, lo encontré en la web para un reloj con displays 7 segmentos.


Code: [Select]


int ocup=0;
int disp=0;
long duracion1, distancia1, duracion2, distancia2, duracion3, distancia3, duracion4, distancia4;


byte Digit[10][8] =
  {  { 1,1,1,1,1,1,0,0 },    // 0
     { 0,1,1,0,0,0,0,0 },    // 1
     { 1,1,0,1,1,0,1,0 },    // 2
     { 1,1,1,1,0,0,1,0 },    // 3
     { 0,1,1,0,0,1,1,0 },    // 4    
     { 1,0,1,1,0,1,1,0 },    // 5
     { 1,0,1,1,1,1,1,0 },    // 6
     { 1,1,1,0,0,0,0,0 },    // 7
     { 1,1,1,1,1,1,1,0 },    // 8
     { 1,1,1,0,0,1,1,0 }     // 9
   };

void setup() {
 Serial.begin(9600); // inicia el puerto serial a 9600 baudios
 pinMode(2, OUTPUT); // define el pin 2 como salida (trigger)
 pinMode(3, INPUT); // define el pin 3 como entrada (echo1)
 pinMode(4, OUTPUT);  // define el pin 4 como salida (Leds1)
 pinMode(5, INPUT);  // define el pin 5 como entrada (echo2)
 pinMode(6, OUTPUT); // define el pin 6 como salida (leds2)
 pinMode(7, INPUT); // define el pin 7 como entrada (echo3)
 pinMode(8, OUTPUT);  // define el pin 8 como salida (leds3)
 pinMode(9, INPUT);  // define el pin 9 como entrada (echo4)
 pinMode(10, OUTPUT);  // define el pin 10 como salida (leds4)

 for (int i= 43; i<54; i++)
       pinMode(i, OUTPUT);
}

void loop() {
  digitalWrite(2, LOW);
  delayMicroseconds(2);
  digitalWrite(2, HIGH); // genera el pulso de 10 us
  delayMicroseconds(10);
  digitalWrite(2, LOW);

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

 
  if (distancia1 >=1 && distancia1 <=49){
     digitalWrite(4, LOW);
    }
    
  if (distancia1 >=50 && distancia1 <=499){
     digitalWrite(4, HIGH);
    }
    
   digitalWrite(2, HIGH); // genera el pulso de 10 us
  delayMicroseconds(10);
  digitalWrite(2, LOW);

  duracion2 = pulseIn(5, HIGH); // capturamos la duración del pulso
  distancia2 = (duracion2/2)/29; // calcula la distancia en cms

 

  if (distancia2 >=2 && distancia2 <=49){
     digitalWrite(6, LOW);
  }

  if (distancia2 >=50 && distancia2 <=499){
     digitalWrite(6, HIGH);
  }

  
  digitalWrite(2, HIGH); // genera el pulso de 10 us
  delayMicroseconds(10);
  digitalWrite(2, LOW);

  duracion3 = pulseIn(7, HIGH); // capturamos la duración del pulso
  distancia3 = (duracion3/2)/29; // calcula la distancia en cms


  if (distancia3 >=2 && distancia3 <=49){
     digitalWrite(8, LOW);
  }

  if (distancia3 >=50 && distancia3 <=499){
     digitalWrite(8, HIGH);
  }

   digitalWrite(2, HIGH); // genera el pulso de 10 us
  delayMicroseconds(10);
  digitalWrite(2, LOW);

  duracion4 = pulseIn(9, HIGH); // capturamos la duración del pulso
  distancia4 = (duracion4/2)/29; // calcula la distancia en cms

 
  if (distancia4 >=2 && distancia4 <=49){
     digitalWrite(10, LOW);
  }

  if (distancia4 >=50 && distancia4 <=499){
     digitalWrite(10, HIGH);
  }

  if (digitalRead(4)==0){
    ocup=ocup+1;}
  if (digitalRead(4)==1){
    disp=disp+1;}

  if (digitalRead(6)==0){
    ocup=ocup+1;}
  if (digitalRead(6)==1){
    disp=disp+1;}

  if (digitalRead(8)==0){
    ocup=ocup+1;}
  if (digitalRead(8)==1){
    disp=disp+1;}  

  if (digitalRead(10)==0){
    ocup=ocup+1;}
  if (digitalRead(10)==1){
    disp=disp+1;}  
      
 
   int k = disp * 100 + ocup ;
    CalculaDigitos(k) ;

}

void Display(int pos, int N)
{  digitalWrite(50,LOW);      // Apaga todos los digitos
   digitalWrite(51,LOW);
   digitalWrite(52,LOW);
   digitalWrite(53,LOW);    
  
    for (int i= 0 ; i<8 ; i++)
             digitalWrite(i+43 , Digit[N][i]);
            
    digitalWrite(50 + pos, HIGH); // Enciende el digito pos
 
 delay(1);
 ocup=0;
 disp=0;

}

void CalculaDigitos(int Num)
{
  
  int Digit0 = ocup %10 ;
  int Digit1 = (ocup % 100) / 10 ;
  int Digit2 = disp %10 ;
  int Digit3 = (disp % 100) / 10 ;
  
  Display(3 , Digit3);
  Display(2 , Digit2);
  Display(1 , Digit1);
  Display(0 , Digit0);

 }



Aquí encontré el código.

https://www.prometec.net/display-4digitos/#modal (https://www.prometec.net/display-4digitos/#modal)

Creo que el error puede estar en esta parte,



Code: [Select]
for (int i= 0 ; i<8 ; i++)
            digitalWrite(i+43 , Digit[N][i]);
            
   digitalWrite(50 + pos, HIGH); // Enciende el digito pos

delay(1);
ocup=0;
disp=0;


cuando cambio el 50 por 51 ó 52, esa salida funciona bien y los demás displays parpadean, espero que puedas ayudarme con esta duda.
Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: surbyte on Aug 13, 2018, 06:50 pm
ANalizando el código. LUego te doy mi devolución.

Esta parte

Code: [Select]
HC_SR04
Pin 2, trigger
Pin 3, echo
Pin 4, led rojo (1 - 49 cms)
Pin 4, led verde (50 - 499 cms)
 
Distancia = (Duración/2)/29
Vel Sonido = 340 m/s
Vel Sonido =(1/29 cm)/us*/


No corresponde a ún código de modo que edita lo que posteaste para que se entienda.

Faltan #includes, faltan definiciones de pines.... verifica. o danos el enlace de donde copiaste.

MI sugerencia es que uses la librería SevenSeg (https://playground.arduino.cc/Main/SevenSeg) entonces ella se encarga via un timer y los pines correspondientes al multiplexado de los 4 displays y tu solo chequeas usando tu código los sensores ultrasónicos y actualizas las variables.
Este es un ejemplo simple

Code: [Select]
#include <SevenSeg.h>

SevenSeg disp(11,7,3,5,6,10,2); // pines para segmentos

const int numOfDigits=4;
int digitPins[numOfDigits]={12,9,8,13}; // pines para digitos.

void setup() {
 
  disp.setDigitPins(numOfDigits, digitPins);



void loop() {

    disp.write(13.28);  // presenta un valor con decimal

}


Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: Gastonc4 on Aug 14, 2018, 07:00 pm
Este es el código que usé, como lo dije, lo encontré en la web para un reloj con displays 7 segmentos

Code: [Select]


int ocup=0;
int disp=0;
long duracion1, distancia1, duracion2, distancia2, duracion3, distancia3, duracion4, distancia4;


byte Digit[10][8] =
  {  { 1,1,1,1,1,1,0,0 },    // 0
     { 0,1,1,0,0,0,0,0 },    // 1
     { 1,1,0,1,1,0,1,0 },    // 2
     { 1,1,1,1,0,0,1,0 },    // 3
     { 0,1,1,0,0,1,1,0 },    // 4  
     { 1,0,1,1,0,1,1,0 },    // 5
     { 1,0,1,1,1,1,1,0 },    // 6
     { 1,1,1,0,0,0,0,0 },    // 7
     { 1,1,1,1,1,1,1,0 },    // 8
     { 1,1,1,0,0,1,1,0 }     // 9
   };

void setup() {
 Serial.begin(9600); // inicia el puerto serial a 9600 baudios
 pinMode(2, OUTPUT); // define el pin 2 como salida (trigger)
 pinMode(3, INPUT); // define el pin 3 como entrada (echo1)
 pinMode(4, OUTPUT);  // define el pin 4 como salida (Leds1)
 pinMode(5, INPUT);  // define el pin 5 como entrada (echo2)
 pinMode(6, OUTPUT); // define el pin 6 como salida (leds2)
 pinMode(7, INPUT); // define el pin 7 como entrada (echo3)
 pinMode(8, OUTPUT);  // define el pin 8 como salida (leds3)
 pinMode(9, INPUT);  // define el pin 9 como entrada (echo4)
 pinMode(10, OUTPUT);  // define el pin 10 como salida (leds4)

 for (int i= 43; i<54; i++)
       pinMode(i, OUTPUT);
}

void loop() {
  digitalWrite(2, LOW);
  delayMicroseconds(2);
  digitalWrite(2, HIGH); // genera el pulso de 10 us
  delayMicroseconds(10);
  digitalWrite(2, LOW);

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

 
  if (distancia1 >=1 && distancia1 <=49){
     digitalWrite(4, LOW);
    }
    
  if (distancia1 >=50 && distancia1 <=499){
     digitalWrite(4, HIGH);
    }
    
   digitalWrite(2, HIGH); // genera el pulso de 10 us
  delayMicroseconds(10);
  digitalWrite(2, LOW);

  duracion2 = pulseIn(5, HIGH); // capturamos la duración del pulso
  distancia2 = (duracion2/2)/29; // calcula la distancia en cms

 

  if (distancia2 >=2 && distancia2 <=49){
     digitalWrite(6, LOW);
  }

  if (distancia2 >=50 && distancia2 <=499){
     digitalWrite(6, HIGH);
  }

 
  digitalWrite(2, HIGH); // genera el pulso de 10 us
  delayMicroseconds(10);
  digitalWrite(2, LOW);

  duracion3 = pulseIn(7, HIGH); // capturamos la duración del pulso
  distancia3 = (duracion3/2)/29; // calcula la distancia en cms


  if (distancia3 >=2 && distancia3 <=49){
     digitalWrite(8, LOW);
  }

  if (distancia3 >=50 && distancia3 <=499){
     digitalWrite(8, HIGH);
  }

   digitalWrite(2, HIGH); // genera el pulso de 10 us
  delayMicroseconds(10);
  digitalWrite(2, LOW);

  duracion4 = pulseIn(9, HIGH); // capturamos la duración del pulso
  distancia4 = (duracion4/2)/29; // calcula la distancia en cms

 
  if (distancia4 >=2 && distancia4 <=49){
     digitalWrite(10, LOW);
  }

  if (distancia4 >=50 && distancia4 <=499){
     digitalWrite(10, HIGH);
  }

  if (digitalRead(4)==0){
    ocup=ocup+1;}
  if (digitalRead(4)==1){
    disp=disp+1;}

  if (digitalRead(6)==0){
    ocup=ocup+1;}
  if (digitalRead(6)==1){
    disp=disp+1;}

  if (digitalRead(8)==0){
    ocup=ocup+1;}
  if (digitalRead(8)==1){
    disp=disp+1;}

  if (digitalRead(10)==0){
    ocup=ocup+1;}
  if (digitalRead(10)==1){
    disp=disp+1;}
    
 
   int k = disp * 100 + ocup ;
    CalculaDigitos(k) ;

}

void Display(int pos, int N)
{  digitalWrite(50,LOW);      // Apaga todos los digitos
   digitalWrite(51,LOW);
   digitalWrite(52,LOW);
   digitalWrite(53,LOW);  
 
    for (int i= 0 ; i<8 ; i++)
             digitalWrite(i+43 , Digit[N][i]);
            
    digitalWrite(50 + pos, HIGH); // Enciende el digito pos
 
 delay(1);
 ocup=0;
 disp=0;

}

void CalculaDigitos(int Num)
{
 
  int Digit0 = ocup %10 ;
  int Digit1 = (ocup % 100) / 10 ;
  int Digit2 = disp %10 ;
  int Digit3 = (disp % 100) / 10 ;
 
  Display(3 , Digit3);
  Display(2 , Digit2);
  Display(1 , Digit1);
  Display(0 , Digit0);

 }




y este es el enlace de donde lo saqué.

https://www.prometec.net/display-4digitos/#modal (https://www.prometec.net/display-4digitos/#modal)

Estoy usando displays de cátodo común y como lo dije funciona, pero 3 de ellos parpadean y la luminosidad es bastante baja.




Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: Gastonc4 on Aug 16, 2018, 10:37 pm
Hola,
Como comenté, no soy experto en programación y algunas cosas no entiendo, perdón por mi ignorancia.

Este ejemplo simple no lo entiendo mucho:


Code: [Select]
#include <SevenSeg.h>

SevenSeg disp(11,7,3,5,6,10,2); // pines para segmentos

const int numOfDigits=4;
int digitPins[numOfDigits]={12,9,8,13}; // pines para digitos.

void setup() {
 
  disp.setDigitPins(numOfDigits, digitPins);

}

void loop() {

    disp.write(13.28);  // presenta un valor con decimal

}


En qué parte debo insertar la parte del còdigo donde hago las lecturas de los sensores y la actualizaciòn de las variables?
osea, esta parte:

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

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

 
  if (distancia1 >=1 && distancia1 <=49){
     digitalWrite(4, LOW);
    }
   
  if (distancia1 >=50 && distancia1 <=499){
     digitalWrite(4, HIGH);
    }
   
   digitalWrite(2, HIGH); // genera el pulso de 10 us
  delayMicroseconds(10);
  digitalWrite(2, LOW);

  duracion2 = pulseIn(5, HIGH); // capturamos la duración del pulso
  distancia2 = (duracion2/2)/29; // calcula la distancia en cms

 

  if (distancia2 >=2 && distancia2 <=49){
     digitalWrite(6, LOW);
  }

  if (distancia2 >=50 && distancia2 <=499){
     digitalWrite(6, HIGH);
  }

 
  digitalWrite(2, HIGH); // genera el pulso de 10 us
  delayMicroseconds(10);
  digitalWrite(2, LOW);

  duracion3 = pulseIn(7, HIGH); // capturamos la duración del pulso
  distancia3 = (duracion3/2)/29; // calcula la distancia en cms


  if (distancia3 >=2 && distancia3 <=49){
     digitalWrite(8, LOW);
  }

  if (distancia3 >=50 && distancia3 <=499){
     digitalWrite(8, HIGH);
  }

   digitalWrite(2, HIGH); // genera el pulso de 10 us
  delayMicroseconds(10);
  digitalWrite(2, LOW);

  duracion4 = pulseIn(9, HIGH); // capturamos la duración del pulso
  distancia4 = (duracion4/2)/29; // calcula la distancia en cms

 
  if (distancia4 >=2 && distancia4 <=49){
     digitalWrite(10, LOW);
  }

  if (distancia4 >=50 && distancia4 <=499){
     digitalWrite(10, HIGH);
  }

  if (digitalRead(4)==0){
    ocup=ocup+1;}
  if (digitalRead(4)==1){
    disp=disp+1;}

  if (digitalRead(6)==0){
    ocup=ocup+1;}
  if (digitalRead(6)==1){
    disp=disp+1;}

  if (digitalRead(8)==0){
    ocup=ocup+1;}
  if (digitalRead(8)==1){
    disp=disp+1;}

  if (digitalRead(10)==0){
    ocup=ocup+1;}
  if (digitalRead(10)==1){
    disp=disp+1;}
   
 
   int k = disp * 100 + ocup ;
    CalculaDigitos(k) ;




al parecer debo reemplazar los pines para segmentos y dígitos por los que uso.

Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: Pablo_Lucini on Aug 17, 2018, 04:03 am
Perdón por la intromisión. Pero es importante usar displays a leds ? Podés usar un LCD ? Si fuera así podés poner uno de 4 lineas de 20 caracteres ( en el que mostrás mucha más información que los de 7 segmentos) y manejás todo el display I2C con 2 salidas. Así liberarías mas pines de tu Arduino.
 
Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: Gastonc4 on Aug 17, 2018, 06:32 am
Pablo, todas las opiniones y sugerencias son bienvenidas y agradezco mucho el interés en ayudar.

Definitivamente si debo usar los displays, por petición del cliente y además el tamaño de la información mostrada debe ser bien grande.

Creo que el problema que tengo en el multiplexado no es del código, ya he probado con otros y se presenta el mismo problema de inestabilidad, me atrevo a pensar que los sensores ultrasónicos generan algún tipo de interferencia o ruido el cual hace que se presenta dicha situación.

Voy a tratar de montar en una tarjeta los sensores y los leds, y en la otra manejar el multiplexado pero tengo que investigar un poco sobre la comunicación I2C para poder enviar los datos desde el maestro hacia el esclavo.
Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: surbyte on Aug 17, 2018, 04:04 pm
Pero yo te sugerí que pruebes el uso de una librerìa que resolverà el problema de multiplexado del display.
Ni siquiera la has probado porque volviste a poner un còdigo similar al primero.

Intenta por esa vìa, la librerìa usa TIMER y te libera del manejo y control del display y solo te tienes que enfocar en el resto.

Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: Gastonc4 on Aug 17, 2018, 06:06 pm
Hola Surbyte,

Te comenté que no entendí mucho el ejemplo simple que me enviaste, en qué parte debo insertar la parte de la lectura de los sensores y actualización de las variables.

Code: [Select]
#include <SevenSeg.h>

SevenSeg disp(11,7,3,5,6,10,2); // pines para segmentos

const int numOfDigits=4;
int digitPins[numOfDigits]={12,9,8,13}; // pines para digitos.

void setup() {
 
  disp.setDigitPins(numOfDigits, digitPins);

}

void loop() {

    disp.write(13.28);  // presenta un valor con decimal

}


Supongo que debo cambiar los pines que están en el ejemplo por los que estoy usando para los displays, pero en la parte del void loop no se que teno que agregar  disp.write(13.28);  que significa?. Si cargo este ejemplo en mi tarjeta, que sucede? sale algo en los displays?
Podrías enviarme un ejemplo para un solo sensor o algo que después pueda continuar solo, te lo agradecería mucho.
Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: surbyte on Aug 17, 2018, 09:38 pm
Ahh disculpa ahora lo leo.
Ya te ayudo con el tema.

Code: [Select]
SevenSeg disp(11,7,3,5,6,10,2); // pines para segmentos
Estos son los segmentos desde a b c d e f g y dp cuenta y verás.

Code: [Select]
int digitPins[numOfDigits]={12,9,8,13}; // pines para digitos.

Esto para los  digitos.. ahora solo hay que verificar si esta para CATODO COMUN o ANODO COMUN en cuyo caso habra que poner una etiqueta para que cambie o invierta.

Este simple comando

Code: [Select]
disp.write(13.28);  // presenta un valor con decimal

presentaría 13.28 en tu display

En tu caso

Code: [Select]
disp.write(distancia1);

luego de calculada debería ser suficiente para que la muestre.
Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: Gastonc4 on Aug 24, 2018, 09:52 pm
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.
Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: surbyte on Aug 25, 2018, 09:12 pm
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?
Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: Gastonc4 on Aug 26, 2018, 03:23 am
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.
Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: Gastonc4 on Sep 21, 2018, 01:25 am
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.



Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: surbyte on Sep 21, 2018, 01:45 am
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 (https://forum.arduino.cc/index.php?topic=276309.0)
Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: Gastonc4 on Sep 21, 2018, 03:10 am
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.

Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: surbyte on Sep 21, 2018, 04:32 am
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.
Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: Gastonc4 on Sep 21, 2018, 07:57 pm
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.
Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: IgnoranteAbsoluto on Sep 22, 2018, 12:38 am
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.




Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: surbyte on Sep 22, 2018, 01:13 am
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

Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: IgnoranteAbsoluto on Sep 22, 2018, 02:06 am
@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.
Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: IgnoranteAbsoluto on Sep 22, 2018, 09:22 pm
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.
Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: Gastonc4 on Sep 25, 2018, 02:24 am
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...
Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: Gastonc4 on Sep 26, 2018, 06:07 pm
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.
Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: surbyte on Sep 26, 2018, 08:44 pm
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;
    }
Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: Gastonc4 on Sep 28, 2018, 05:56 am
Hola,

Funciona, gracias a las correcciones por fin pude hacer que funcionara, claro que estoy por ahora trabajando con el simulador Proteus y a medida que fui colocando los sensores ultrasónicos con los leds, se fue poniendo un poco más lento, yo diría que cada cambio en los sensores demora unos 10 segundos para reflejarse.
No se que tanto en el montaje real se pueda volver lento ya que el código es bastante largo.
Incluí la parte del multiplexado con 2 displays 7 segmentos de ánodo común, los cuales van a mostrar los puestos disponibles, empieza en 24 y a medida que se enciende un led, la variable "disp" toma el valor de "disp = disp-1". Incluye la librería timerOne, la cual encontré en la web y sólo tuve que hacerle algunas modificaciones, aunque quiero aclarar que no entiendo muy bien esa parte, sólo se que funciona. Hay un video donde el autor del código explica con mucho detalle como se desarrolla, voy a dejar el enlace y tambén donde está el código escrito.

https://www.youtube.com/watch?v=XnAf2ZQS8GY (https://www.youtube.com/watch?v=XnAf2ZQS8GY)

https://pastebin.com/fsikttET (https://pastebin.com/fsikttET)

Y mi código va así por el momento, voy a colocar hasta 4 sensores, pero en realidad queda más largo, ya que va hasta el sensor 24.

Code: [Select]
#include <TimerOne.h>

//Ánodo común
byte num [10]={
  3,    //0 00000011
  159,  //1 10011111
  37,   //2 00100101
  13,   //3 00001101
  153,  //4 10011001
  73,   //5 01001001
  65,   //6 01000001
  31,   //7 00011111
  1,    //8 00000001
  25    //9 00011001

};

const byte DS_1=A11, SHCP=A12, STCP_1=A13, DS_2=A14, STCP_2=A15, displays=2;
unsigned long  i, j=1, sep [displays], disp=24, z, k=0;
float y;
unsigned long int ahora, antes;

unsigned long ocup=0;
long duracion1, distancia1, duracion2, distancia2, duracion3, distancia3, duracion4, distancia4;
long duracion5, distancia5, duracion6, distancia6, duracion7, distancia7, duracion8, distancia8;
long duracion9, distancia9, duracion10, distancia10, duracion11, distancia11, duracion12, distancia12;
long duracion13, distancia13, duracion14, distancia14, duracion15, distancia15, duracion16, distancia16;
long duracion17, distancia17, duracion18, distancia18, duracion19, distancia19, duracion20, distancia20;
long duracion21, distancia21, duracion22, distancia22, duracion23, distancia23, duracion24, distancia24;

const byte latchPinLeds = 53;    //Pin conectado a ST_CP of 74HC595
const byte clockPinLeds = 51;    //Pin conectado a SH_CP of 74HC595
const byte dataPinLeds =  52;     //Pin connected to DS of 74HC595

void setup() {
   pinMode(latchPinLeds, OUTPUT);
   pinMode(clockPinLeds, OUTPUT);
   pinMode(dataPinLeds, OUTPUT);
   pinMode(0, OUTPUT);  pinMode(1, INPUT);  
   pinMode(2, OUTPUT);  pinMode(3, INPUT);  
   pinMode(4, OUTPUT);  pinMode(5, INPUT);  
   pinMode(6, OUTPUT);  pinMode(7, INPUT);
   pinMode(8, OUTPUT);  pinMode(9, INPUT);
   pinMode(10, OUTPUT);  pinMode(11, INPUT);
   pinMode(12, OUTPUT);  pinMode(13, INPUT);
   pinMode(14, OUTPUT);  pinMode(15, INPUT);
   pinMode(16, OUTPUT);  pinMode(17, INPUT);
   pinMode(18, OUTPUT);  pinMode(19, INPUT);
   pinMode(20, OUTPUT);  pinMode(21, INPUT);
   pinMode(22, OUTPUT);  pinMode(23, INPUT);
   pinMode(24, OUTPUT);  pinMode(25, INPUT);
   pinMode(26, OUTPUT);  pinMode(27, INPUT);
   pinMode(28, OUTPUT);  pinMode(29, INPUT);
   pinMode(30, OUTPUT);  pinMode(31, INPUT);
   pinMode(32, OUTPUT);  pinMode(33, INPUT);
   pinMode(34, OUTPUT);  pinMode(35, INPUT);
   pinMode(36, OUTPUT);  pinMode(37, INPUT);
   pinMode(38, OUTPUT);  pinMode(39,INPUT);
   pinMode(40, OUTPUT);  pinMode(41,INPUT);
   pinMode(42, OUTPUT);  pinMode(43, INPUT);
   pinMode(44, OUTPUT);  pinMode(45, INPUT);
   pinMode(46, OUTPUT);  pinMode(47, INPUT);
   pinMode(DS_1, OUTPUT);
   pinMode(SHCP, OUTPUT);
   pinMode(STCP_1, OUTPUT);
   pinMode(DS_2, OUTPUT);
   pinMode(STCP_2, OUTPUT);

   Timer1.initialize(1000);
   Timer1.attachInterrupt(mostrar);
 }

void loop() {
 ocup = 0; // Ponemos a cero todos los bits
  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){ // No hace falta más para saber que está a nivel alto
        ocup |= 1 << 0; // Ponemos a 1 el bit 0
        disp=disp-1;
 }

  digitalWrite(2, LOW);
  delayMicroseconds(2);
  digitalWrite(2, HIGH); // genera el pulso de 10 us
  delayMicroseconds(10);
  digitalWrite(2, LOW);
  duracion2 = pulseIn(3, HIGH); // capturamos la duración del pulso
  distancia2 = (duracion2/2)/29; // calcula la distancia en cms
    
   if (distancia2 >=2 && distancia2 <=299){
        ocup |= 1 << 1; // Ponemos a 1 el bit 1
        disp=disp-1;
  }

  digitalWrite(4, LOW);
  delayMicroseconds(2);
  digitalWrite(4, HIGH); // genera el pulso de 10 us
  delayMicroseconds(10);
  digitalWrite(4, LOW);
  duracion3 = pulseIn(5, HIGH); // capturamos la duración del pulso
  distancia3 = (duracion3/2)/29; // calcula la distancia en cms
    
    if (distancia3 >=2 && distancia3 <=299){
        ocup |= 1 << 2; // Ponemos a 1 el bit 2
        disp=disp-1;
  }
  
  digitalWrite(6, LOW);
  delayMicroseconds(2);
  digitalWrite(6, HIGH); // genera el pulso de 10 us
  delayMicroseconds(10);
  digitalWrite(6, LOW);
  duracion4 = pulseIn(7, HIGH); // capturamos la duración del pulso
  distancia4 = (duracion4/2)/29; // calcula la distancia en cms  
    
    if (distancia4 >=2 && distancia4 <=299){
        ocup |= 1 << 3; // Ponemos a 1 el bit 3
        disp=disp-1;
  }

   // A continuación se mandan los dos bytes del entero
  digitalWrite(latchPinLeds,LOW);
  shiftOut(dataPinLeds, clockPinLeds, MSBFIRST, (ocup & 0x00ff0000) >> 16);
  shiftOut(dataPinLeds, clockPinLeds, MSBFIRST, (ocup & 0x0000ff00) >> 8); // Primero el byte más significativo
  shiftOut(dataPinLeds, clockPinLeds, MSBFIRST, (ocup & 0x000000ff));
  digitalWrite(latchPinLeds, HIGH);


ahora=millis();
   z=disp;
    for (i=0; i<=(displays-1); i++){
      y=z%10;
      sep [(displays-1-i)]= y;
      z=int((z/10));
    disp=24;  
    }
 
}

void mostrar()
{  
  if(j==pow(2,displays))j=1;
  if(k==displays)k=0;
 
  digitalWrite (STCP_2, LOW);
  shiftOut(DS_2, SHCP, MSBFIRST, 0);
  digitalWrite (STCP_2, HIGH);
 
  digitalWrite (STCP_1, LOW);
  shiftOut(DS_1, SHCP, LSBFIRST, num[ sep[k] ]);
  digitalWrite (STCP_1, HIGH);
 
  shiftOut(DS_1, SHCP, LSBFIRST, 0 >> 8);
 
  digitalWrite (STCP_2, LOW);
  shiftOut(DS_2, SHCP, MSBFIRST, j);
  digitalWrite (STCP_2, HIGH);
  j=j*2; k=k+1;
}
  


Quisiera saber si hay forma de hacer un array o los que sean necesarios para reducir la lectura de los sensores, ya para los leds hay uno que envió @ignoranteAbsoluto, pero ese está basado en lectura de los pines digitales, habría que modificarlo para que lea los sensores y así se vayan encendiendo los leds.
De todos modos, esto para mi ha sido muy provechoso, ya que con cada indicación que he recibido en este foro, he ido avanzando y aprendiendo un poco más. Voy a intentar modificar y buscar la forma de reducir el código, cualquier sugerencia será bienvenida. Estaré informando de como va todo.
Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: surbyte on Sep 28, 2018, 05:05 pm
Que pena que no tomaste la indicación de IgnoranteAbsoluto, primero porque esta muy optimizada en cuanto a un código rápido dentro de lo que tu quieres (ya has visto que la manera mas veloz es la que te sugerí o incluso se puede mejorar) pero partiendo de ahi seguramente tendrías toda la flexibilidad.

A mi la parte que usas PulseIN no me gusta. Si hay algo lento es

Code: [Select]
duracion1 = pulseIn(1, HIGH); // capturamos la duración del pulso

Cuanto tarda eso? no lo se.. hasta que encuentra el pulso en HIGH.
Por eso prefiero las librerias como NewPing.h (http://playground.arduino.cc/Code/NewPing) que te recomiendo incluso tiene un ejemplo para leer 15 sensores ultrasónicos secuencialmente.
Asi que facilmente adaptable a tu caso de 4.

El unico problema que veo es que es timer-interrupted o sea que si usa la misma interrupción que tu TimerOne no servirá.


Porque no subes tu simulacion en un archivo .zip para poder seguirte mejor.
Creo que mas alla que no tengo claro a que apuntas en el proyecto, deberías empezar a prestar atención a los tiempos que consume cada cosa y si algo consume demasiado tiempo entonces hay que ver porque o considerar modificar el enfoque por algo mas rápido.


NOTA: La librería NewPing usa Timer2 para el UNO de modo que no habrá problemas.
Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: Gastonc4 on Sep 29, 2018, 03:44 am
Bueno, aquí voy a subir la simulación en proteus, como dije, anda un poco lenta y a partir del sensor20 se frenaba y me decía que había algo desconectado y por más que lo corregía, siempre se detenía, al fin opté por retirar los sensores del 20al 24, por ahora están trabajando 19 sensores.
En la simulación ya aparecen los 2 displays 7 segmentos, 3 barras de leds y los 19 sensores ultrasónicos, voy a adjuntar la librería del sensor y el código completo con los 24 sensores.

La opción de @IgnoranteAbsoluto no está descartada, sólo que por el momento tendría que estudiarla un poco más para poder adaptarla a la lectura de los sensores.

Quedo atento a todo.


Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: surbyte on Sep 29, 2018, 10:00 pm
Pero claro como no va a estar lento...

A ver mi amigo, un simulador se usa para resolver situaciones digamos lógicas. Has puesto 21 sensores ultrasónicos, 24 leds que me parece bien mas los leds 7 segmentos  por dios hace falta todo eso?

Además tu código.. te hable de NewPing.h que hace las cosas fáciles y en tu código tienes 24 rutinas repetidas una para cada sensor ultrasónico!!!

No te pareció que merece un poco de simplificación?

Bueno le meto mano y tijera por todos lados para reducir ese código.

Aprecio y valoro tu esfuerzo pero insisto!!! En algún punto el sentido común dicta que algo no puede ser... asi que es mejor detenerse y preguntar, Cómo hago para reducir 24 sensores ultrasónicos de modo mas eficiente? Es posible?

Ese es un punto, es posible?

EDITO 1:

El ejemplo de NewPing tiene 15 y tu usas 24. No me cuesta nada copiar y pegar el ejemplo cambiar la variable que define la cantidad de sensores y ponerle 24 pero eso es viable? No lo se en la práctica.

Veré como mejorar tu código e invito a los programadores a que den sus versiones que lógicamente serán mejores que la mía.

Creo que estamos perdiendo el objetivo.
Asi que voy a sugerirte algo aún a pesar de que esto pueda funcionar como está.
Veo un problema de implementación práctica importante:

El montaje de 24 sensores y sus cables a que distincia estarán?
Supongamos un auto que tiene un ancho de 2 mts o menos
Mi camioneta mide 1.5 mts, el de mi Sra mide 1.8 mts con espejos.
Una Camioneta tipo Toyota 4x4 1.8 mts

Asi que si supusieramos 2.5 mts entre sensores estaríamos bien.
Supondré tmb que tienes 12 espacios enfrentados o sea que si pongo el sensor al centro, el mas alejado estará a

11x2.5+1.75 = 29.25 mts
O sea que tus dos sensores mas alejado estarán a casi 30 mts y luego reducimos en 2.5 los siguientes.
Dime como harás para que tu mega envie los los pulsos a esa distancia?

Es momento como te digo de replantear todo.

Vas a tener que distribuir sensore con algun Arduino NANO por ejemplo que envie los datos via Radio al Arduino de tu elección.
Sino me parece que estas condenado a fallar.

EDITO 2: Revisando NewPing.h veo que dice

Quote
Each sensor is pinged at 33ms intervals. So, one cycle of all sensors takes 495ms (33 * 15 = 495ms).
Cada sensor demora 33 mseg en ser chequeado y el loop demora 495 para 15 sensores.

Si pasamos a 24 tendremos 33 x 24 = 792 mseg

Ese tiempo es viable, si claro.. menos de 1 segundo para barrer los 24 sensores si fuera posible no es un tiempo prohibitivo. El problema es las distancias a cada sensor.

Aun suponiendo que estuvieras en el centrol del estacionamiento tendrías a los sensores mas alejados (4) a 15 mts. Sigue siendo una distancia importante y sujeta a ruidos electromagnéticos de todo tipo.

Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: Gastonc4 on Sep 30, 2018, 01:44 am
Wao, esto parece complicarse un poco, pero nadie dijo que sería fácil, yo de algo atrevido u osado dije: yo puedo hacerlo y aquí estoy metido en esta situación.

He tenido situaciones donde las distancias son un pequeño problema, pero aveces en la práctica simplemente me arriesgo y me han funcionado, espero que esta no sea la excepción, contamos con cable utp cat 6E el cual recomienda distacias de hasta 50 mts para algunas situaciones, de todo modos antes de tomar decisiones tengo que ir probando los sensores más alejados a ver como nos va, pero claro que es un tema preocupante.

Con respecto al código, voy a ir probando a ver hasta donde llego, he estado leyendo la librería NewPing y haré el ejemplo ampliándolo a 24 a ver si logro que funcione. De todos modos quisiera preocuparme por ahora más por el código que quede más reducido y eficiente en cuanto a velocidad, si logro algo, no dudaré en mostrarlo y si hay alguna idea de cómo debe quedar, claro que será bienvenida.

Gracias amigo Surbyte por toda esta guía que he recibido de tu parte, aunque con tropiezos, este proyecto va tomando forma superando cada etapa.
Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: surbyte on Sep 30, 2018, 05:21 pm
ya tengo el código con 24. Te lo paso. Lo hice ayer.

Code: [Select]
// ---------------------------------------------------------------------------
// This example code was used to successfully communicate with 15 ultrasonic sensors. You can adjust
// the number of sensors in your project by changing SONAR_NUM and the number of NewPing objects in the
// "sonar" array. You also need to change the pins for each sensor for the NewPing objects. Each sensor
// is pinged at 33ms intervals. So, one cycle of all sensors takes 495ms (33 * 15 = 495ms). The results
// are sent to the "oneSensorCycle" function which currently just displays the distance data. Your project
// would normally process the sensor results in this function (for example, decide if a robot needs to
// turn and call the turn function). Keep in mind this example is event-driven. Your complete sketch needs
// to be written so there's no "delay" commands and the loop() cycles at faster than a 33ms rate. If other
// processes take longer than 33ms, you'll need to increase PING_INTERVAL so it doesn't get behind.
// ---------------------------------------------------------------------------
#include <NewPing.h>

#define SONAR_NUM     22 // Number of sensors.
#define MAX_DISTANCE 200 // Maximum distance (in cm) to ping.
#define PING_INTERVAL 33 // Milliseconds between sensor pings (29ms is about the min to avoid cross-sensor echo).

unsigned long pingTimer[SONAR_NUM]; // Holds the times when the next ping should happen for each sensor.
unsigned int cm[SONAR_NUM];         // Where the ping distances are stored.
uint8_t currentSensor   = 0;          // Keeps track of which sensor is active.
unsigned long ocup      = 0;
const byte DS_1 = A11;
const byte latchPinLeds = 53;    //Pin conectado a ST_CP of 74HC595
const byte clockPinLeds = 51;    //Pin conectado a SH_CP of 74HC595
const byte dataPinLeds =  52;     //Pin connected to DS of 74HC595

NewPing sonar[SONAR_NUM] = {     // Sensor object array.
  NewPing( 0,  1, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping.
  NewPing( 2,  3, MAX_DISTANCE),
  NewPing( 4,  5, MAX_DISTANCE),
  NewPing( 6,  7, MAX_DISTANCE),
  NewPing(10, 11, MAX_DISTANCE),
  NewPing(12, 13, MAX_DISTANCE),
  NewPing(14, 15, MAX_DISTANCE),
  NewPing(16, 17, MAX_DISTANCE),
  NewPing(18, 19, MAX_DISTANCE),
  NewPing(20, 21, MAX_DISTANCE),
  NewPing(22, 23, MAX_DISTANCE),
  NewPing(24, 25, MAX_DISTANCE),
  NewPing(26, 27, MAX_DISTANCE),
  NewPing(28, 29, MAX_DISTANCE),
  NewPing(30, 31, MAX_DISTANCE),
  NewPing(32, 33, MAX_DISTANCE),
  NewPing(34, 35, MAX_DISTANCE),
  NewPing(36, 37, MAX_DISTANCE),
  NewPing(38, 39, MAX_DISTANCE),
  NewPing(40, 41, MAX_DISTANCE),
  NewPing(42, 43, MAX_DISTANCE),
  NewPing(46, 47, MAX_DISTANCE)
};

void setup() {
  Serial.begin(115200);
  pingTimer[0] = millis() + 75;           // First ping starts at 75ms, gives time for the Arduino to chill before starting.
  for (uint8_t i = 1; i < SONAR_NUM; i++) // Set the starting time for each sensor.
    pingTimer[i] = pingTimer[i - 1] + PING_INTERVAL;
  pinMode(DS_1, OUTPUT);
}

void loop() {
  for (uint8_t i = 0; i < SONAR_NUM; i++) { // Loop through all the sensors.
    if (millis() >= pingTimer[i]) {         // Is it this sensor's time to ping?
      pingTimer[i] += PING_INTERVAL * SONAR_NUM;  // Set next time this sensor will be pinged.
      if (i == 0 && currentSensor == SONAR_NUM - 1) oneSensorCycle(); // Sensor ping cycle complete, do something with the results.
      sonar[currentSensor].timer_stop();          // Make sure previous timer is canceled before starting a new ping (insurance).
      currentSensor = i;                          // Sensor being accessed.
      cm[currentSensor] = 0;                      // Make distance zero in case there's no ping echo for this sensor.
      sonar[currentSensor].ping_timer(echoCheck); // Do the ping (processing continues, interrupt will call echoCheck to look for echo).
    }
  }
  // Other code that *DOESN'T* analyze ping results can go here.
}

void echoCheck() { // If ping received, set the sensor distance to array.
  if (sonar[currentSensor].check_timer())
    cm[currentSensor] = sonar[currentSensor].ping_result / US_ROUNDTRIP_CM;
}

void oneSensorCycle() { // Sensor ping cycle complete, do something with the results.
  // The following code would be replaced with your code that does something with the ping results.
  for (uint8_t i = 0; i < SONAR_NUM; i++) {
      // Serial.print(i);
      // Serial.print("=");
      // Serial.print(cm[i]);
      // Serial.print("cm ");
      if (cm[i] >=2 && cm[i] <= 299){
          ocup |= (unsigned long) 1 << i;
         // disp=disp-1;
      }

  }
  // A continuación se mandan los dos bytes del entero
  digitalWrite(latchPinLeds,LOW);
  shiftOut(dataPinLeds, clockPinLeds, MSBFIRST, (ocup & 0x00ff0000) >> 16);
  shiftOut(dataPinLeds, clockPinLeds, MSBFIRST, (ocup & 0x0000ff00) >> 8); // Primero el byte más significativo
  shiftOut(dataPinLeds, clockPinLeds, MSBFIRST, (ocup & 0x000000ff));
  digitalWrite(latchPinLeds, HIGH);

}



Con esto vi que los leds de las barras funcionaban aparentemente bien.

Mi sugerencia en este punto es que pruebes con 4 sensores Ultrasonicos con la idea de que ATmega este en el centro del estacionamiento y colocas los 4 sensores en los puntos mas alejados. Si funcionan pues adelante.

Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: Gastonc4 on Oct 02, 2018, 04:08 am
Hola Surbyte,
Hay que hacer alguna modificación al código? , porque así como está, no me funciona.
No me he atrevido a modificar algo todavía, ya que esto es un poco avanzado para mi, esto de usar librerías se me dificulta un poco, por ahora sigo con la simulación y veo que en ésta los pines trigger aparecen en gris, no se vuelven azules como sucede con los otros códigos.
Tu idea de empezar con los 4 sensores más alejados me parece genial, es lo primero que haré en la parte física.
Si hay que modificar algo, no dudes en decirme, o si hay que modificar algo en el circuito.
Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: surbyte on Oct 02, 2018, 02:20 pm
La idea de empezar por los 4 mas alejados es probar si es factible que funcione.
Si esa prueba no funciona tendras que usar NANOs (es mi caballito de batalla siempre) y algun medio de Radio como nRF24L01 para subdividir en sectores todo el estacionamiento. Que cada NANO controle la cantidad de sensores primero que pueda y luego que lo haga sin fallas.

Que fallo tuvo el código porque yo lo probé y no fallaba.
Title: Re: Multiplexar datos que vienen de varias placas de Arduino.
Post by: Gastonc4 on Nov 13, 2018, 06:15 pm
Hola,

Después de unas semanas de receso he vuelto con el proyecto casi terminado en su parte teórica.

Los códigos están funcionando perfectamente, algunos ya en la implementación física y la interacción entre si va por buen camino.

La prueba de los sensores más alejados ya la realizé, éstos son 2 y quedan alejados del circuito principal a una distancia aproimada de 20 mts y su funcionamiento es muy bueno, esta esra la parte más precupante pero utilizando un cable utp cat 6E y una buena fuente de 5V 5A no tuvimos problemas.

La única parte que faltaba era la transmisión de los datos a un servidor por medio de la shield Ethernet W5100, pero ya encontré la forma de hacerlo, hay muchos ejemplos en la web de esta shield y los datos voy a tomarlos desde los leds utilizando las 24 señales que vienen desde los 74595 y ahora hago el proceso a la inversa utilizando el integrado CD4021 que es un registro de desplazamiento paralelo-serie. Envío los datos a los 4021 y la salida son sólo 3 pines, pero para esto voy a hacer un circuito independiente con un Arduino Uno y la Shield Ethernet, así aunque gaste un poco más de dinero me parece la opción más viable ya que contamos con esas tarjetas y sería totalmente independiente del Mega que ya estaría controlado los sensores, los leds y los displays.

La parte física del proyecto se llevará a cabo esta semana, iré contado como va el proceso y dando los detalles que más pueda.

Quiero reiterar mi agradecimiento a Surbyte e Ignorante Absoluto, gracias a ustedes este proceso no lo hubiese podido implementar, aunque no se ha dicho la última palabra en cuanto a su funcionamiento, todo esto ha sido más fácil gracias a sus aportes.