Maestro-esclavo y TFT LCD

Hola, espero que puedan ayudarme, no logro la comunicación de 2 Arduino UNO a través de Rx/Tx(si, los tengo cruzados) pero aun así no se muestra nada en la TFT.

Hola, tengo problemas para comunicar dos Arduino UNO a través de los puertos Rx/Tx (Si, los tengo invertidos) pero aun así los datos censados no se muestran en la tft. 
Este el código para el transmisor
//Oxigeno disuelto en agua/////////////////////////////////////////////////////
#include <SoftwareSerial.h>                           //we have to include the SoftwareSerial library, or else we can't use it
#define rx 2                                          //define what pin rx is going to be
#define tx 3                                          //define what pin tx is going to be
SoftwareSerial DOsen(rx, tx);                         //define how the soft serial port is going to work
boolean sensor_string_complete = false;               //have we received all the data from the Atlas Scientific product

//Ph/////////////////////////////////////////////////////
const int analogInPin = A0; 
int sensorValue = 0; 
unsigned long int avgValue; 
float b;
int buf[10],temp;

//TEMP/////////////////////////////////////////////////////
#include <OneWire.h>
#include <DallasTemperature.h>
const int pinTemp = 4;
OneWire oneWireObjeto(pinTemp);
DallasTemperature TEMP(&oneWireObjeto);

//Flujometro/////////////////////////////////////////////////////
int     pinFlow = 11;
float   k = 7.5;
int     sinicio;
long    tinicio;
long    subida;
long    periodo;
float   frecuencia;
boolean sobretiempo;

//Turbiedad///////////////////////////////////////////////
int pinTurb = 1;

//General////////////////////////////////////////////////
int     esp = 1300;
boolean rdysen1;
boolean rdysen2;
boolean rdysen3;
boolean rdysen4;
boolean rdysen5;
String  val1 = "";
float   val2;
float   val3;
float   val4;
float   val5;


void setup() {
  Serial.begin(9600); //set baud rate for the hardware serial port_0 to 9600

 //DO///////////////////////////////////////////////////////
  DOsen.begin(9600);  //set baud rate for the software serial port to 9600
  val1.reserve(30);   //set aside some bytes for receiving data from Atlas Scientific product

 //Temp///////////////////////////////////////////////////////
  TEMP.begin(); 

 //Flow///////////////////////////////////////////////////////
  pinMode (pinFlow, INPUT);
  
 //General////////////////////////////////////////////////////
  rdysen1 = false;
  rdysen2 = false;
  rdysen3 = false;
  rdysen4 = false;
  rdysen5 = false;
  
  delay (1000);
}

void loop() {
//DO/////////////////////////////////////////
  val1 = "";
  while ((DOsen.available() > 0) && (sensor_string_complete == false)){  //if we see that the Atlas Scientific product has sent a character
    char inchar = (char)DOsen.read();                                    //get the char we just received
    if (inchar == '\r') {                                                //if the incoming character is a <CR>
    sensor_string_complete = true;                                       //set the flag
    }else{
      val1 += inchar;
    }
  }

  if (sensor_string_complete == true) {               //if a string from the Atlas Scientific product has been received in its entirety
    rdysen1 = true;
    sensor_string_complete = false;                   //reset the flag used to tell if we have received a completed string from the Atlas Scientific product
  }
 
//PH/////////////////////////////////////
  for(int i=0;i<10;i++) 
   { 
    buf[i]=analogRead(analogInPin);
    delay(10);
   }
   for(int i=0;i<9;i++)
   {
    for(int j=i+1;j<10;j++)
    {
     if(buf[i]>buf[j])
     {
      temp=buf[i];
      buf[i]=buf[j];
      buf[j]=temp;
     }
    }
   }
   avgValue=0;
   for(int i=2;i<8;i++)
   avgValue+=buf[i];
   float pHVol=(float)avgValue*5.0/1024/6;
   float val2 = -5.70 * pHVol + 21.34;
   delay(20);
   rdysen2 = true;

//TEMP/////////////////////////////////////
  TEMP.requestTemperatures();
  val3 = TEMP.getTempCByIndex(0);
  rdysen3 = true;

//Flow/////////////////////////////////////
  sobretiempo = false;
  sinicio = digitalRead(pinFlow);
  tinicio = millis();
  while((digitalRead(pinFlow) == sinicio) && (sobretiempo == false)){
    if ((millis()-tinicio)>500){
      sobretiempo = true;
    }
  }
  subida = millis();
  while((digitalRead(pinFlow) != sinicio) && (sobretiempo == false)){
  }
  while((digitalRead(pinFlow) == sinicio) && (sobretiempo == false)){
  }
  if(sobretiempo == false){
    periodo = millis() - subida;
    frecuencia = 1000 / periodo;
  }else{
    frecuencia = 0;
  }
  val4 = frecuencia / k;
  rdysen4 = true;

//Turbiedad///////////////////////////////////////////////////////////////////////
  int AnaTurb = analogRead(pinTurb);
  float val5 = 5.25 - 0.006*AnaTurb; 
  rdysen5 = true;
  
//Transmisión//////////////////////////////
  if ((rdysen1 == true) && (rdysen2 == true) && (rdysen3 == true) && (rdysen4 == true) && (rdysen5 == true)){
    Serial.print("A");
    Serial.print("DOxy");
    Serial.print(" = ");
    int i=0;
    while (val1[i] != ','){
      Serial.print(val1[i]);
      i++;
    }
    val1 = "";
    delay (esp);
    
    Serial.print("B");
    Serial.print("Ph  ");
    Serial.print(" = ");
    Serial.print(val2);
    delay (esp);    
  
    Serial.print("C");
    Serial.print("Temp");
    Serial.print(" = ");
    Serial.print(val3);
    delay (esp);

    Serial.print("D");
    Serial.print("Flow");
    Serial.print(" = ");
    Serial.print(val4);
    delay (esp);    
  
    Serial.print("E");
    Serial.print("Turb");
    Serial.print(" = ");
    Serial.print(val5);
    delay (esp);

    Serial.println("");

    rdysen1 = false;
    rdysen2 = false;
    rdysen3 = false;
    rdysen4 = false;
    rdysen5 = false;
  }
}

Este es el código para el receptor

#include <Adafruit_GFX.h> // Libreria de graficos
#include <Adafruit_TFTLCD.h> // Libreria de LCD 
#include <SD.h>              // Libreria de tarjeta SD
#include <SPI.h>             
 
// Pines de conexion del LCD
#define LCD_CS A3 // Chip Select - Pin analogico 3
#define LCD_CD A2 // Command/Data - Pin Analogico 2
#define LCD_WR A1 // LCD Write - Pin Analogico 1
#define LCD_RD A0 // LCD Read - Pin Analogico 0
#define LCD_RESET A4 // LCD Reset - Pin Analogico 4
 
#define SD_CS 10
#define BUFFPIXEL 20  
Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);  // Instancia LCD
 
#define BLACK 0x0000 // Definimos los colores para poder referirnos a ellos con su nombre
#define RED 0xF800 // en lugar de usar el código hexadecimal de cada uno.
#define GREEN 0x07E0
#define WHITE 0xFFFF
#define BLUE 0x001F
#define CYAN 0x07FF
#define YELLOW 0xFFE0
#define MAGENTA 0xF81F

boolean start;
boolean rdysen1;
boolean rdysen2;
boolean rdysen3;
boolean rdysen4;
boolean rdysen5;

String lectura = "";
String sen1 = "";
String sen2 = "";
String sen3 = "";
String sen4 = "";
String sen5 = "";

void setup() {
  Serial.begin(9600);
  tft.reset();
  tft.begin(0x9341); 
  if (!SD.begin(SD_CS)){
    Serial.println(F("Error!"));
    return;
  }
  Serial.println(F("OK!"));

  tft.setRotation(3); // Establecemos la posicion de la pantalla Vertical
 // bmpDraw("1.bmp",<0); // Mostramos una imagen en las coordenadas 0,0
  delay(1000);
  
  tft.fillScreen(BLUE); // Colocamos el fondo del LCD en Negro
  tft.setRotation(3); // Establecemos la posición de la pantalla Vertical u Horizontal
  tft.setTextColor(WHITE); // Definimos el color del texto 
  tft.setTextSize(2);
  tft.setCursor(20, 10); // Situamos el cursor en la posicion del LCD deseada,  
  tft.print("Esperando datos..."); 

  lectura.reserve(20);
  sen1.reserve(20); 
  sen2.reserve(20);
  sen3.reserve(20);
  sen4.reserve(20);
  sen5.reserve(20);

  rdysen1 = false;    //"false" si sensor activo
  rdysen2 = false;    //"false" si sensor activo
  rdysen3 = false;    //"false" si sensor activo
  rdysen4 = false;    //"false" si sensor activo
  rdysen5 = false;    //"false" si sensor activo

  delay (500);
}

void loop() {
  start = false;

  while (Serial.available()>0){
      lectura = Serial.readStringUntil(13);
      start = true;
  }  
  /////////////////////////////////////////////////////////////////
  
  if((start == true) && (lectura[0] == 'A')){
    sen1 = lectura;
    rdysen1 = true;
  }

  if((start == true) && (lectura[0] == 'B')){
    sen2 = lectura;
    rdysen2 = true;
  }

  if((start == true) && (lectura[0] == 'C')){
    sen3 = lectura;
    rdysen3 = true;
  }

  if((start == true) && (lectura[0] == 'D')){
    sen4 = lectura;
    rdysen4 = true;
  }

  if((start == true) && (lectura[0] == 'E')){
    sen5 = lectura;
    rdysen5 = true;
  }

  //////////////////////////////////////////////////////////////////

  if ((rdysen1 == true) && (rdysen2 == true) && (rdysen3 == true) && (rdysen4 == true) && (rdysen5 == true)){
    tft.fillScreen(BLACK);
    tft.setTextSize(3);
    tft.setCursor(0, 10);   
    
    for (int i=1; i<=20; i++){
      tft.print(sen1[i]);
    }
    tft.println("");

    for (int i=1; i<=20; i++){
      tft.print(sen2[i]);
    }
    tft.println("");

    for (int i=1; i<=20; i++){
      tft.print(sen3[i]);
    }
    tft.println("");

    for (int i=1; i<=20; i++){
      tft.print(sen4[i]);
    }
    tft.println("");

    for (int i=1; i<=20; i++){
      tft.print(sen5[i]);
    }
    tft.println("");
    
    rdysen1 = false;    //"false" si sensor activo
    rdysen2 = false;    //"false" si sensor activo
    rdysen3 = false;    //"false" si sensor activo
    rdysen4 = false;    //"false" si sensor activo
    rdysen5 = false;    //"false" si sensor activo
  }
}

//////////////////////////////////////////////////////////////////////////////////////////
//Carga de imagenes///////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////

void bmpDraw(char *filename, int x, int y) {

  File     bmpFile;
  int      bmpWidth, bmpHeight;   // W+H in pixels
  uint8_t  bmpDepth;              // Bit depth (currently must be 24)
  uint32_t bmpImageoffset;        // Start of image data in file
  uint32_t rowSize;               // Not always = bmpWidth; may have padding
  uint8_t  sdbuffer[3*BUFFPIXEL]; // pixel in buffer (R+G+B per pixel)
  uint16_t lcdbuffer[BUFFPIXEL];  // pixel out buffer (16-bit per pixel)
  uint8_t  buffidx = sizeof(sdbuffer); // Current position in sdbuffer
  boolean  goodBmp = false;       // Set to true on valid header parse
  boolean  flip    = true;        // BMP is stored bottom-to-top
  int      w, h, row, col;
  uint8_t  r, g, b;
  uint32_t pos = 0, startTime = millis();
  uint8_t  lcdidx = 0;
  boolean  first = true;

  if((x >= tft.width()) || (y >= tft.height())) return;

  // Open requested file on SD card
  if ((bmpFile = SD.open(filename)) == NULL) {
    Serial.println(F("File not found"));
    return;
  }

  // Parse BMP header
  if(read16(bmpFile) == 0x4D42) { // BMP signature
    Serial.println(F("File size: ")); Serial.println(read32(bmpFile));
    (void)read32(bmpFile); // Read & ignore creator bytes
    bmpImageoffset = read32(bmpFile); // Start of image data
    Serial.print(F("Image Offset: ")); Serial.println(bmpImageoffset, DEC);
    // Read DIB header
    Serial.print(F("Header size: ")); Serial.println(read32(bmpFile));
    bmpWidth  = read32(bmpFile);
    bmpHeight = read32(bmpFile);
    if(read16(bmpFile) == 1) { // # planes -- must be '1'
      bmpDepth = read16(bmpFile); // bits per pixel
      Serial.print(F("Bit Depth: ")); Serial.println(bmpDepth);
      if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed
        goodBmp = true; // Supported BMP format -- proceed!
        rowSize = (bmpWidth * 3 + 3) & ~3;
        if(bmpHeight < 0) {
          bmpHeight = -bmpHeight;
          flip      = false;
        }
        w = bmpWidth;
        h = bmpHeight;
        if((x+w-1) >= tft.width())  w = tft.width()  - x;
        if((y+h-1) >= tft.height()) h = tft.height() - y;
        tft.setAddrWindow(x, y, x+w-1, y+h-1);
        for (row=0; row<h; row++) { // For each scanline...
          if(flip) // Bitmap is stored bottom-to-top order (normal BMP)
            pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
          else     // Bitmap is stored top-to-bottom
            pos = bmpImageoffset + row * rowSize;
          if(bmpFile.position() != pos) { // Need seek?
            bmpFile.seek(pos);
            buffidx = sizeof(sdbuffer); // Force buffer reload
          }

          for (col=0; col<w; col++) { // For each column...
            // Time to read more pixel data?
            if (buffidx >= sizeof(sdbuffer)) { // Indeed
              // Push LCD buffer to the display first
              if(lcdidx > 0) {
                tft.pushColors(lcdbuffer, lcdidx, first);
                lcdidx = 0;
                first  = false;
              }
              bmpFile.read(sdbuffer, sizeof(sdbuffer));
              buffidx = 0; // Set index to beginning
            }

            // Convert pixel from BMP to TFT format
            b = sdbuffer[buffidx++];
            g = sdbuffer[buffidx++];
            r = sdbuffer[buffidx++];
            lcdbuffer[lcdidx++] = tft.color565(r,g,b);
          } // end pixel
        } // end scanline
        // Write any remaining data to LCD
        if(lcdidx > 0) {
          tft.pushColors(lcdbuffer, lcdidx, first);
        } 
        Serial.print(F("Loaded in "));
      } // end goodBmp
    }
  }

  bmpFile.close();
  if(!goodBmp) Serial.println(F("BMP format not recognized."));
}

uint16_t read16(File f) {
  uint16_t result;
  ((uint8_t *)&result)[0] = f.read(); // LSB
  ((uint8_t *)&result)[1] = f.read(); // MSB
  return result;
}

uint32_t read32(File f) {
  uint32_t result;
  ((uint8_t *)&result)[0] = f.read(); // LSB
  ((uint8_t *)&result)[1] = f.read();
  ((uint8_t *)&result)[2] = f.read();
  ((uint8_t *)&result)[3] = f.read(); // MSB
  return result;
}

Recuerda que si usas Rx y Tx para la comunicación serie, no puedes usar el puerto USB al mismo tiempo.

¿Has probado comentar esta línea en ambos sketches?

  if ((rdysen1 == true) && (rdysen2 == true) && (rdysen3 == true) && (rdysen4 == true) && (rdysen5 == true)){

Recuerda comentar la llave de cierre.

Sobre ese condicional en el código transmisor tengo un comentario, por como está planteado, no tiene sentido.

  if (rdysen1 == true){

Es suficiente porque el resto siempre van a ser verdaderas en ese punto, la única variable que podría ser falsa es rdysen1 que se modifica dentro de un condicional, el resto lo fijas tú incondicionalmente.

Además si ese condicional (el original) no es verdadero (podría suceder si rdysen1 fuese falso) no enviaría el valor de ningún sensor.

Lo mismo pasa en el receptor, si no recibes los 5 valores no imprimes ninguno.

¿Y si falla un sensor?
Dejaría de enviar los datos de todos.
No me parece buena idea.

Creo que la lógica de la recepción está bien (salvo lo del if que no me convence), pero la de envio... no me cierra por ningún lado.
Por eso te sugiero que pruebes comentar esas líneas y ver si al menos recibes los datos de alguno.
Después vemos que se puede corregir.

Saludos

Perfecto, probaré lo que dices, gracias

No hay porqué. Espero tus comentarios.

He hecho lo que me has recomendado, dejé solo la primera condición para ambos casos.
Aun no hay transmisión de datos de ningún sensor. Considero relevante mencionar que los sensores de PH, temperatura y el flujometro, probados en un programa aparte, envían estos valores

PH 7.64
Temp -127
Flow 0.0

Estoy testando en un balde de agua potable.
De esos valores, solo el de PH se logra ver en la TFT a través de la conexión Rx/Tx pero sin programar como maestro/esclavo
Disculpa si parece absurdo lo que escribo, no soy experta en el tema

No te hagas problema, yo tampoco la tengo taaan clara, tambien soy nuevito con arduino. :wink:
Solo que ya he incursionado en la programación de muchos micros (soy de la vieja escuela, comencé programando para Z80 en ensamblador, imagina).

Entonces, ¿PH si llega?
Si es así ¡vamos avanzando!

Reviso con más detalle el código y te cuento que más encuentro.

Super, muchas gracias :slight_smile:

Disculpa pero no me quedó claro.
¿Haciendo la modificación sí pudiste leer pH en la TFT?
¿O sea que uno emitió el pH y el otro lo recibió, pero lo demás no? ¿Es así?

Así es, no tenía la configuración Maestro/esclavo, pero si tenía las placas conectadas, con la modificación, el valor del PH fue el único que se logró ver en la pantalla (como si fuera el monitor serial)

¿El DOxy envía una lista de valores separados por coma? Porque no entiendo por qué al enviar la primer lectura lo haces con un lazo que corta al encontrar una coma. ¿Y los demás valores, si los hay?
Y si no hay tal coma, ¿cuándo sale del while? Yo creo que ahí hay un desastre en puerta.

De hecho acabo de probar ese trozo de código y si el String no tiene una coma, el while sigue "hasta el infinito y más allá".

Suponiendo que hay un único valor, creo que mejor lo cambias por

Serial.print("A");
Serial.print("DOxy");
Serial.print(" = ");
int i=0;
while (val1[i] != 0){    //porque el string siempre termina con byte 0
  Serial.print(val1[i]);
 i++;
}
val1 = "";

Prueba y me cuentas.

Aunque podrías hacer directamente esto

Serial.print("A");
Serial.print("DOxy");
Serial.print(" = ");
Serial.print(val1);
val1 = "";

Simple y sin complicaciones innecesarias.

Gracias por aportar, en cuanto tengamos el sensor haré la modificación y probaré esa parte, ahorita no contamos con ello :confused:

Como dijiste que solo veías el de pH pensé que tenias todos y solo ese funcionaba bien. Bueno...
Pero puedes probar los que si tienes porque ahora no se debería trabar aunque el DOxy no esté (creo...).

Saludos

Supongo que ademas de TX y RX cruzados compartes GND entre ambos Arduinos no?

No lo dices en ningún post.