Compartir el estado de GPIOs con Arduino vía serie (RESUELTO)

Hola a todos!! :wink: , tengo una duda que no soy capaz de resolver, a ver si alguien conoce la respuesta.

Estoy haciendo un proyecto en el que una Raspberry se comunica con un Arduino nano mediante los GPIO de las Raspberry, esto lo hago cableando los GPIO de las Raspberry a las entradas digitales del Arduino nano y cuando detecto que se ponen en HIGH o LOW las uso en el mi sketch. Mi pregunta es la siguiente:

¿Se puede hacer lo mismo usando un cable USB haciendo uso de la comunicación serie entre las dos placas?

He visto tutoriales sobre como activar la comunicación serie entre el Arduino y la Raspberry pero no se explica nada sobre como usar las activaciones de los GPIO y compartir su estado para usarlos en mi sketch de Arduino.

Gracias y un saludo.

Estoy en la misma disyuntiva de @ArduMyth. No comprendo si lo que quieres es leer los datos del NANO via USB desde el Raspi? Si es asi es tema para otro foro.

Te adelanto que si, lo he visto en Python y no es dificil. En otros lenguajes como C++ requiere mas habilidad pero se consigue.

Busca el foro raspberry.org en espaÑol y plantea ahi la pregunta.

Recuerda, usa el idioma del foro, siempre.

Hola surbyte y ArduMyth, siento si la pregunta no era la indicada para este foro, creo que lo más correcto sera empezar preguntando mi duda en foros de Raspberry, de todas formas el problema que planteo es a dos bandas y cuando tenga claro como iniciar la comunicación serie con la Raspberry tendre que ver como manejar esos datos en un programa de Arduino.

En la Raspberry tengo que investigar como saber los GPIOs que hay activos y crear una palabra de confirmación para enviar por serie al arduino el cual estará escuchando hasta encontrar la palabra o string esperado.

La parte que necesito hacer en Arduino es recibir una palabra o dato enviado desde la Raspberry y usarlo en mi código, por ejemplo ahora lo que yo hago en mi programa de Arduino es que si esta activa la entrada 6 que ocurra una cosa y si esta activa la entrada 5 que ocurra otra, pues tengo que cambiar la parte esa del codigo y poner algo como que cuando reciba del puerto serie "hola" que ocurra una cosa y si recibo por el serie "adios" que ocurra otra.
Me imagino que en el condicional de mi código tendré que usar la librería serial para que segun lo que reciba de la Raspberry ocurra una cosa u otra ¿cierto?, no se si sabeis de algún ejemplo en el que apoyarme para ir aprendiendo este método y una vez que lo entienda ya ir complicandome más.

Gracias por todo.

Si es Mario290386, los GPIO son como los pines de Arduino. Tendrás que crear código en Raspberry PI para que cuando ocurra un cambio en cierto pin te envía un numero de codigo por el puerto serie.

Luego de recibido en Arduino ese código es interpretado posiblemente mediante un switch.. case

No te complique simplemente codifica algo asi:

0 = No pasa nada
1 = Se abrio puerta
2 = Ventilador prendido
3 = mucho frio
etc

Para probar el arduino solo intenta con el monitor serie y haz lo que te dice @kike_GL y simulas que el Raspi le esta enviando esos códigos.
Asi puedes descartar una parte.

Gracias por la info!! estoy ya investigando como obtener los valores de los GPIO de la Raspi y estoy almacenándolos en variables para poder enviar 0, 1 y 2 que son los 3 estados que quiero mandar por puerto serie al Arduino.

Una pregunta más ¿Es posible enviar estos datos al puerto del Arduino nano usando la conexión que tiene el Arduino nano? es un cable USB similar al los que usa el mando de PS3, es importante para mi que los datos puedan transmitirse por este cable ya que yo uso este tipo de Arduinos y es el único cable con el que se puede conectar a la Raspi.

Gracias de nuevo!!

Por supuesto que puedes enviarle datos via USB. Pero ya te dijimos que esa pregunta es para el foro Raspi no para este.

Via USB el Arduino lee todo como entrada Serie. Asi que solo tienes que manejar el puerto USB segun sea reconocido por el raspi
Tienes muchos ejemplos en Google de como unir Raspi y Arduino por USB. no entiendo como no los has buscado.

Veo que este tema se repite y la mayoría de la gente no sabe buscar en internet.

Google: raspberry arduino usb y te aseguro que tienes todo usando Python, otro usando C otro usando el lenguaje que quieras y mas te agrade.

Hola surbyte !! Voy poco a poco progresando con mi proyecto, he conseguido establecer comunicación del lado de la Raspi usando el puerto serie y al conectar el Arduino me lo detecta. :slight_smile:

Ahora me surge un pequeño problema en el lado del Arduino, tal y como me recomendó Kike_GL estoy haciendo pruebas con un sketch sencillo y el monitor de puerto serie para intentar que el Arduino actúe en función de si recibe un 1 o un 2.

Este es el código que he realizado de prueba:

int va;
void setup() {
  Serial.begin(9600);
}


void loop() { 

  while (Serial.available()== 0){
    Serial.println("OFF");
    delay (400);
    }
 

  
  if(Serial.available()>0){
     va=Serial.read();
 


     while(va=='1') {
    
   Serial.println("Modo 1");
   delay (400);
      }
  }

  
  while (va=='2') {
     Serial.println("Modo 2");
     delay (400);
    
    }    
  }

Os resumo lo que hace mi programa:

Si no se detecta comunicación por el puerto serie se imprime "OFF"
Si se detecta un "1" por el puerto serie se imprime "Modo 1"
Si se detecta un "2" por el puerto serie se imprime "Modo 2"

En principio el programa me funciona, el problema lo tengo en el tratamiento de los bucles.
Resulta que si le envío "1" me imprime "Modo 1" pero al enviar un "2" no consigo que me entre al "Modo 2" realmente no se de que manera puedo hacerlo, lo he intentado con bucles while o if else e incluso he usado un GOTO para intentar redirigir el programa al otro bucle pero nunca consigo que me cambie al modo 2 una vez que entra en el primer bucle.

No se de que manera proceder,y no se si debería probar con un switch case o interrumpir el programa de alguna manera.
Por favor necesito una mano, solo me falta esta parte para completar la comunicación de forma correcta.

Gracias!

Bueno de lo que no te has dado cuenta por ser parcialmente desordenado y ahora que te explique entenderas a que me refiero.
Cuando trabajes con códigos usa siempe sangria, o sea, cada nivel y subnivel debe estar debidamente tabulado para que facilite la lectura. Mira esto:

  if (Serial.available()>0) {
      va = Serial.read();
 
      while(va=='1') {
        Serial.println("Modo 1");
        delay (400);
      }
  }

  
  while (va=='2') {
     Serial.println("Modo 2");
     delay (400);
    
  }

Cada vez que recibes datos del puerto serie sea 1 y 2 el único al que le prestas atención es a '1' porque '2' esta fuera del bucle donde se leen los datos

Entonces lo que debes hacer es esto

int va;

void setup() {
  Serial.begin(9600);
}

void loop() { 

  if (Serial.available()>0) {
      va = Serial.read();
 
      switch (va) {
        case '1': Serial.println("Modo 1");
                  break;
        case '2': Serial.println("Modo 2");
                  break;
      } 
  } // fin de lectura de datos del puerto serie
}

Hola!! es cierto que estaba mi programa muy desordenado.

He probado el código que me has pasado y funciona el problema que no me sirve su funcionamiento por un detalle que olvide comentar, haber si lo se explicar:

lo que necesito es que el programa este imprimiendo continuamente “Modo 1” en bucle infinito y al pulsar 2 necesito que este imprimiendo “Modo 2” en bucle infinito y si pulso nuevamente 1 que me imprima “Modo 1”infinitamente y así sucesivamente. De la manera que tu me comentas solo se imprime una sola vez.

Si pruebas mi sketch veras que funciona de esta manera, el problema es que cuando entra en un while no se como sacar al programa de ahí ya que necesito que el programa este pendiente ante el cambio al pulsar "2"

Este funcionamiento tan extraño lo necesito porque tengo una panel led programable con 3 estados distintos, y para mostrar cada uno de los estados necesito que el programa se quede cíclicamente ejecutando el bucle, si solo hace un print no daria tiempo a mostra nada por la pantalla led, el problema como ves lo tengo en como conseguir que el arduino se quede en bucle ejecutando y a la vez pendiente de hacer el cambio de estado.

Gracias

Saludos!!

Pues es muy fácil, adjunto el código, te recomiendo que enves de delay utilices millis ya que segun tu programa se haga mas grande te va a presentar mayor problemas

int va;

void setup() {
	Serial.begin(9600);
}

void loop() {

	if (Serial.available()>0) {
		va = Serial.read();
	} // fin de lectura de datos del puerto serie
	switch (va) {
	case '1': 
		Serial.println("Modo 1");
		delay(400);
		break;
	case '2': 
		Serial.println("Modo 2");
		delay(400);
		break;
	}
}

Bien!! esto ya se va pareciendo a lo que necesito, he modificado el código porque le faltaba el estado "OFF":

int va;

void setup() {
  Serial.begin(9600);
}

void loop() {
Serial.println("OFF");
delay(400);


  while (Serial.available()>0) {
    delay(400);

    va = Serial.read();
  } // fin de lectura de datos del puerto serie
  
  switch (va) {
  case '1': 
    Serial.println("Modo 1");
    delay(400);
    break;
  case '2': 
    Serial.println("Modo 2");
    delay(400);
    break;
  }
}

Lo que me falla es la parte del "OFF", necesito conseguir que si no hay comunicación serie se imprima "OFF" en bucle infinito.
Ahora lo que me ocurre es que al pulsar 1 o 2 se va alternando "Estado 1" y OFF infinitamente, el "OFF" no debería de salir mientras pulso 1 o 2.

Mil gracias!!

Bueno en esta caso al mandar un numero que no sea 1 o 2 te mostrará "OFF".

int va;

void setup() {
	Serial.begin(9600);
}

void loop() {
	while (Serial.available()>0) {
		va = Serial.read();
	} // fin de lectura de datos del puerto serie

	switch (va) {
	case '1':
		Serial.println("Modo 1");
		delay(400);
		break;
	case '2':
		Serial.println("Modo 2");
		delay(400);
		break;
	default:
		Serial.println("OFF");
		delay(400);
	}
}

Hola Swift, muchas gracias por tu ayuda llevava 2 dias atrancado con esto, luego lo pruebo cuando llegue a casa y te confirmo si me funciona.

Tengo la duda si el default que has añadido se ejecuta nada iniciarse el programa o si se tiene que cumplir primero la condicion del primer while, lo que yo necesito es que nada mas arrancar el programa empiece a mandar “OFF” hasta que yo mande un 1 o 2.

Saludos!!

Pues no sería necesario el while que este lo que estaría haciendo sería mientras haya algo en el puerto serial lee y asignalo en la variable va por lo cual con un if sería más que suficiente y hace lo mismo.

int va = 0;

void setup() {
	Serial.begin(9600);
}

void loop() {
	if (Serial.available() > 0) {
		va = Serial.read();
	} // fin de lectura de datos del puerto serie

	switch (va) {
	case '1':
		Serial.println("Modo 1");
		delay(400);
		break;
	case '2':
		Serial.println("Modo 2");
		delay(400);
		break;
	default:
		Serial.println("OFF");
		delay(400);
	}
}

Ahora al iniciar el programa inicia hay algo en el puerto serial NO entonces continúa al switch y evalúa, como val = 0 y no hay ningún caso te estaría mostrando el por defecto "OFF" y eso hasta que mandes 1 o 2 y con eso ya cambiaría para tus dos estados ahora si mandas 3 también te mostrará "OFF" ya que 3 no tienen ningún caso.

Esta comprobado y funciona PERFECTO!!! mil gracias :slight_smile: :slight_smile: De verdad estaba que no sabia que mas hacer y al final un switch case era la solución jejej.
Saludos.

Ah por cierto, eso de que poniendo "3" se vuelve a poner en OFF me viene de LUJO, nose como lo hace pero me viene que ni pintado :slight_smile: :slight_smile:

Bueno evidentemente deberias ponerte a estudiar un poco porque luego del empujón inicial tendrías que haber arrancado como se dice. Y mas si interactuas con Raspberry.
Ve a Documentación y mira en Indice de temas tutoriales las clases de Youtube. Te servirán
Si el tema esta solucionado edita el titulo del primer hilo con un [SOLUCIONADO]