[Solucionado] Comunicación de dos arduinos

Buenas tardes,

Necesito una ayuda, tengo un proyecto con dos arduinos, un arduino Uno y un arduino Mega. En el Uno tengo varios sensores de humedad y temperatura, y en el arduino mega tengo programada una pantalla TFT.

Lo que necesito es enviar el valor de la humedad y la temperatura que tengo en el arduino Uno y enviarlos por alguno de los puertos Tx para utilizarlo en el arduino mega, la verdad no he podido hacerlo, si alguien me puede dar un ejemplo o si no se puede por favor háganmelo saber

Gracias !!!

¿Qué es lo que no puedes? TX Uno a RX Mega, GND con GND; simple-.

Pregunta: Porque dos arduinos? Si es porque estan conectados a distancia utiliza modulos NRF24L01+ inalambricos, coloca el sketch para ver que estas haciendo...

pues suena simple pero no se como se hace en programación ósea como debo mandar los datos o que librerías se usan no tengo conocimiento y no uso un modulo inalámbrico porque están bastante cerca entonces no lo creo necesario

Bueno tienes dos formas de codificar la información: texto o binario. Si la frecuencia de actualización de los datos debe ser alta, yo optaría por la segunda; aunque es algo difícil de comprender, es la manera más ágil de trabajar para un sistema digital.

Lo primero a saber, son los tipos de dato y su rango de valores: temperatura... ¿es un float? Humedad... ¿otro float o es un número entero que va del 0 al 100?
Lo segundo a saber es: ¿debo enviar un flujo de datos constante? ¿O solo cuando se le solicita?.

Responde ese par de preguntas y continuaré con el tema.

Si creo que la solución es mandarla Binario, pues los dos son Float y pues lo mejor seria que todo el tiempo se este enviando, dime puedes ayudar indicándome que se debe hacer la verdad esto no lo conozco muy bien

josue_gonzalezm:
Si creo que la solución es mandarla Binario, pues los dos son Float y pues lo mejor seria que todo el tiempo se este enviando

En forma binaria no he visto tutoriales que expliquen cómo se hace, así que lo haré a como mejor pueda.

En AVR (en tu caso ambos Arduino Uno y Mega), un float se almacena en 4 bytes; ya que vamos a trasmitir dos de estos (temperatura y humedad), pues lógicamente tendremos que enviar 8 bytes en cada "paquete" (conjunto de ambos datos).
Sabiendo esto último, tendremos claro que el receptor debe esperar al menos que 8 bytes hayan llegado antes de procesar la información. Este detalle formará parte del código base para el receptor.

El emisor requiere de dos pasos: lectura de sensores (implícitamente también cuenta la parte de almacenar los valores en variables) y transmisión de los 8 bytes. En código, se vería así:

void loop() {
  // Paso 1:
  float temperatura = // Obtención de la temperatura
  float humedad =  // Obtención de la humedad
  // A partir de aquí aprenderás algo nuevo. Paso 2:

  Serial.write((byte*)&temperatura, 4); // Envío de la temperatura, en forma binaria
  Serial.write((byte*)&humedad, 4); // Envío de la humedad, en forma binaria
  delay(10); // Valor de ensayo y error. Evita llenar el búfer del receptor en caso de que este sea más lento que el emisor; cosa que muy probablemente ocurra ya que el microcontrolador no tiene procesador dedicado a los gráficos.
  // Un valor muy alto podría hacer que el flujo de datos deje de ser "constante".
}

El receptor realiza tres pasos: recibir la información, "reconstruir" los valores originales y mostrarlos en pantalla.

void loop() {
  if (Serial.available() > 7) { // Este es básicamente el paso 1. Con que la condición se cumpla, ya tenemos los dos datos listos para procesar
    // Paso 2:
    float temperatura = 0.0;
    float humedad = 0.0; // Se inicializan de una vez para que ocupen (reserven) espacio en la memoria. Más adelante se explicará sobre esto.

    Serial.readBytes((byte*)&temperatura, 4);
    Serial.readBytes((byte*)&humedad, 4); // Por el orden de los datos, se supone que la temperatura es primero, luego la humedad.

    // Paso 3: imprimir en pantalla los valores de ese par de variables.
  }
  // No se requiere de delay porque aquí es el emisor quien determina la frecuencia con que los datos se deben actualizar.
}

Ahora explicaré con detalle esa función que quizá para ti sea una novedad:

Serial.write((byte*)&temperatura, 4);

write y print no son lo mismo (excepto cuando el parámetro es del tipo char o un array de este tipo). Para no contar el "cuento largo", write se utiliza para "escribir" o enviar bytes, mientras que print genera una representación textual de mútiples tipos de datos (no solo bytes).

La parte (byte*)&temperatura quiere decir que el contenido de la variable temperatura será interpretado como un array de byte (de ahí que sea posible descomponerlo en un grupo de bytes).
Los caracteres '*' y '&' pertenecen al famoso tema de los punteros de memoria; en este caso específico se utilizan para que write obtenga los bytes directamente de donde está ubicada (en memoria) la variable.

El número 4 determina la cantidad de bytes por enviar. No podemos valernos de sizeof para determinar el tamaño de un array que se pasa por referencia mediante punteros, esa es la razón de este parámetro.

readBytes cuenta una historia similar, aunque... ¿recuerdas la parte donde dije que las variables tenían que estar inicializadas de antemano? Pues como la función requiere el puntero de la variable, ¿de dónde lo obtendría si no se ha reservado su espacio? No estoy seguro si la falta de inicialización hubiera parado en un error de compilación o de ejecución, pero en cualquier caso el objetivo de esto es evitarnos un dolor de cabeza.

Uff, creo que eso es todo lo que tenía que decir. Ojalá y no se me haya escapado algún detalle :sweat_smile:

Uy perfecto mas detalle que ese creo que imposible, listo ahora lo voy a probar con los dos arduinos a ver como funciona todo, Muchas Gracias !!

Hola.. ya lo prove le cambie unas cosas porque me aparecía un error mira como los puse, pero igual no funciona :S

Lo probe con un solo sensor de temperatura y dos arduinos Mega

Maestro:

#include <DallasTemperature.h>
#include <OneWire.h>
#include <Wire.h>

#define PinDig_1 22 // Termocupla Pin 2

OneWire oneWire1(PinDig_1);

DallasTemperature sensor1(&oneWire1);

void setup() {
Serial.begin(9600);
Wire.begin(); // join i2c bus (address optional for master)
sensor1.begin();
Wire.begin();
}

void loop() {
sensor1.requestTemperatures(); //Indica que el sensor se va a leer
float temperatura1 = sensor1.getTempCByIndex(0); //Se lee el valor que me da la termocupla
Wire.beginTransmission(1);
Wire.write("Temp is "); // sends five bytes
Wire.write((byte*)&temperatura1, 4); // sends one byte
Wire.endTransmission(); // stop transmitting
Serial.println(temperatura1);
delay(500);

Esclavo

#include <Wire.h>

float temperatura1= 0.0;

void setup()
{
// put your setup code here, to run once:
Serial.begin(9600);
Wire.begin(1);
}

void loop() {
if (Wire.available() > 3)
{
temperatura1=Wire.readBytes((byte*)&temperatura1, 4);
}
Serial.println(temperatura1);
}

Gracias por la ayuda

Quedo pendiente

Te envié privado, por favor edita tu post último.

Wire.write("Temp is ");        // sends five bytes
  Wire.write((byte*)&temperatura1, 4);              // sends one byte

Primero envias un texto de 8 bytes y luego los 4 correspondientes a un valor float. No me sorprende que te aparezcan lecturas incorrectas.
Si es para comunicación entre Arduinos, el envío de texto es solo para casos muy específicos; para todo lo demás, existe Master Card es mejor enviar solo los datos y en forma binaria.

Además estoy un poco sorprendido por como aplicas la arquitectura de I2C; digo, por lo general es el maestro el que pide y recibe los datos; cuando el maestro envía, usualmente es para darle comandos al esclavo.
Yo esperaba que funcionase de la siguiente manera:

  • El maestro es el que controla la pantalla y recibe los datos. Cuando necesita actualizarlos, le solicita (request) al esclavo 4 bytes y ahí es donde se confirma su recepción mediante available.
  • El esclavo es el encargado de hacer las lecturas y transmitirlas al maestro; lo hace únicamente cuando recibe una petición de este.

Hola !!! gracias por tu respuesta, pues la verdad pues dije que el de los sensores era el maestro porque también tengo unos actuadores que necesitan señal PWM entonces con la pantalla no los tengo disponible, pero quería preguntarte, vi el error que tenia de mandar "Temp is" no lo había visto, pero cuando mando los float y los trato de leer por puerto serie de igual manera no me aparecen :S.

Por otro lado vi que no necesariamente se necesita usar la librería Wire, se puede con seria entre los arduinos que supongo es el código que colocaste al principio.. quería preguntar que lo intente así pero aun así no me deja leer los datos :confused:

Gracias amigo !

josue_gonzalezm:
pero cuando mando los float y los trato de leer por puerto serie de igual manera no me aparecen :S.

¿Las conexiones están correctas? Ya sabes:

Lucario448:
TX Uno a RX Mega, GND con GND; simple.

¿Las tasas de baudios coinciden? Recuerda que esta se define en el begin.

Pues ahora como estoy trabajando con dos arduinos mega estoy conectando Tx0 y Rx0 al Tx1 y Rx1 del arduino que tiene la pantalla y estoy uniendo GND con GND y Vcc con Vcc para tener una sola alimentación. Los Baudios están a 9600 de los dos

josue_gonzalezm:
estoy conectando Tx0 y Rx0 al Tx1 y Rx1

Si en el orden en que me lo dices representa a como lo tienes conectado, entonces el problema está en no cruzar la líneas de datos.

¿Dé que sirve la comunicación si entre sí se juntan dos transmisores y dos receptores? Lo lógico es que un transmisor tenga un receptor, ¿no crees?

Pregunta al respecto...... quizás tonta, pero......

Si no están muy lejos lo que veo ilógico es usar dos teniendo un MEGA o incluso solo con el UNO.... en lugar de enviar la información, y poner un cable o cables hacia el otro lado, porque no te llevas los cables del VISOR y haces el código en un solo Arduino.....

Es decir, pones todo en un solo Arduino, y la caja interior o donde quieras colocar la pantalla, te llevas cables hacia la otra caja con un conector y funcionaría igual....... digo yo........

Si el Arduino Mega está en capacidad de manejar todo, bien; sin embargo no tengo idea qué tan largo puede ir SPI...

Hola amigo,

Si claro que estoy conectando tx con rx :

Tx0 con Rx1
Tx1 con Rx0

es necesario usar la función Wire?

josue_gonzalezm:
es necesario usar la función Wire?

¿Para qué? ¿Es por puerto serial la intercomuncación sí o no?
Otro aspecto por verificar, es que la comunicación USB no se esté usando al mismo tiempo que los pines RX0 y TX0.

Tal y como tienes el código, si no lo has cambiado, con

Serial.begin(9600);

Estás utilizando el serial que utiliza el arduíno también para el USB, si estas utilizando la consola para debugar no te va a funcionar.

Prueba con:

Serial1.begin(9600);

tanto en el maestro como en el esclavo y utiliza el Serial1 de los dos MEGAS, si usas un MEGA y un UNO al final en el mega usa el Serial1, y en el UNO utiliza la libreria SoftwareSerial para crear un serial virtual.

Si no utilizas la consola para debugar entonces conecta Pin0 (Mega1) con Pin 1 (Mega2) y viceversa y le mandas las cosas desde el Serial.

Por otro lado, exactamente qué es lo que te está llegando por el puerto serie?

un saludo!