Conexion dos arduinos por uart

Hola! Estoy trabajando en un proyecto y necesito conectar un arduino mega con un arduino uno. Os adjunto el código de lo que he realizado, no sé qué es lo que falla.
Si el interruptor está en alto, mando un dato al arduino mega para que el motor paso a paso se mueva.

//codigo arduino uno

#define EN 8

//Direction pin
#define X_DIR 6

//Step pin
#define X_STP 3

#include <SoftwareSerial.h>

//A498
int delayTime = 600;
int stps=2730;

int dato;
byte fcarrera;


void step(boolean dir, byte dirPin, byte stepperPin, int steps)
{
  digitalWrite(dirPin, dir);
  delay(100);
  for (int i = 0; i< steps; i++)
  {
    digitalWrite(stepperPin, HIGH);
    delayMicroseconds(delayTime);
    digitalWrite(stepperPin, LOW);
    delayMicroseconds(delayTime);
  }
}

void setup()
{
  Serial.begin(9600);
  pinMode(X_DIR, OUTPUT); pinMode(X_STP,OUTPUT);
  pinMode(EN, OUTPUT);
  pinMode(fcarrera,INPUT);
  digitalWrite(EN,LOW);
  digitalWrite(fcarrera,LOW);
}
void loop()
{
//  step(false, X_DIR, X_STP, stps);
//  delay(1000);
//  step(true, X_DIR, X_STP, stps);
//  delay(1000);

  
  //si existe datos disponibles en el bus serial 
  if (Serial.available()>0){
     dato = Serial.read(); //leemos dato
     Serial.println(dato); 
   if (dato =! stps){
    step(false, X_DIR, X_STP, stps);
    delay(1000);
    }
    if (dato == stps){
      step(true, X_DIR, X_STP, stps);
      delay(1000);
      }
    }
}

//arduino mega se encuentra dentro de un menu, la conexion se encuentra al final del código

#include <LiquidCrystal_I2C.h>
#include <LiquidMenu.h>
#include <Servo.h>
#include <SoftwareSerial.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);
Servo servoMotor1B;
Servo servoMotor1A;
Servo servoMotor2A;
Servo servoMotor2B;

//ENCODER
#define outputA 6
#define outputB 7
#define sw 4

int poss_inicial_1AB=210;
int poss_final_1AB=128;
int poss_inicial_2AB=230;
int poss_final_2AB=180;

int aState;
int aLastState;  
int incremento;
int ajuste_1AB=6;
int ajuste_2AB=-8;
int temp1;
int temp2;


//LEDS
#define led1 8
#define led2 9
#define led3 10

int i;
int j;
int RETARD=75;
int led_seleccionado = 0;

//variables compartidas entre arduinos
int dato;
byte fcarrera;
#define fcarrera 13
//SoftwareSerial myserial(19,18);

//lineas pantalla 1 
LiquidLine linea1(1, 0, "INICIO");
LiquidLine linea2(1, 1, "PERFILES");
LiquidLine linea3(1, 0, "CUCHARADA");
LiquidLine linea4(1, 1, "RECOGIDA");

//LiquidScreen pantalla1(linea1,linea2,linea3,linea4);

//lineas pantalla 2
LiquidLine linea1_2(1, 0, "PERFIL 1");
LiquidLine linea2_2(1, 1, "PERFIL 2");
LiquidLine linea3_2(1, 0, "Atras");
//LiquidScreen pantalla2(linea1_2,linea2_2,linea3_2);

//lineas pantalla 3
LiquidLine linea1_3(1, 0, "ACTIVAR");
LiquidLine linea2_3(1, 1, "PROGRAMAR");
LiquidLine linea3_3(1, 0, "Atras");
//LiquidScreen pantalla3(linea1_3,linea2_3,linea3_3);

//lineas pantalla 4
LiquidLine linea1_4(1, 0, "ALTURA");
LiquidLine linea2_4(1, 1, "GIRO  ");
LiquidLine linea3_4(1, 0, "Atras");
//LiquidScreen pantalla4(linea1_4,linea2_4,linea3_4);

//lineas pantalla 5 
LiquidLine linea1_5(1, 0, "AUMENTO");
LiquidLine linea2_5(1, 1, "DISMINUYE");
LiquidLine linea3_5(1, 0, "Atras");
//LiquidScreen pantalla5(linea1_5,linea2_5,linea3_5);

//declaracion de pantallas

LiquidScreen pantalla1;
LiquidScreen pantalla2;
LiquidScreen pantalla3;
LiquidScreen pantalla4;
LiquidScreen pantalla5;

LiquidMenu menu(lcd);

void setup() {

  Serial1.begin(9600);
  servoMotor1B.attach(2);
  servoMotor1A.attach(3);
  servoMotor2B.attach(8);
  servoMotor2A.attach(9);
  pinMode(sw,INPUT_PULLUP);
  
 lcd.init();
  //lcd.begin(16,2);
  lcd.backlight();
  

  menu.init();

 //añadir lineas a pantalla 1 
  pantalla1.add_line(linea1);
  pantalla1.add_line(linea2);
  pantalla1.add_line(linea3);
  pantalla1.add_line(linea4);

  //añadir lineas a pantalla 2 
  pantalla2.add_line(linea1_2);
  pantalla2.add_line(linea2_2);
  pantalla2.add_line(linea3_2);

  //añadir lineas a pantalla 3 
  pantalla3.add_line(linea1_3);
  pantalla3.add_line(linea2_3);
  pantalla3.add_line(linea3_3);

  //añadir lineas a pantalla 4 

  pantalla4.add_line(linea1_4);
  pantalla4.add_line(linea2_4);
  pantalla4.add_line(linea3_4);

  //añadir lineas a pantalla 5

  pantalla5.add_line(linea1_5);
  pantalla5.add_line(linea2_5);
  pantalla5.add_line(linea3_5);
  

  linea1.set_focusPosition(Position::LEFT); 
  linea2.set_focusPosition(Position::LEFT); 
  linea3.set_focusPosition(Position::LEFT); 
  linea4.set_focusPosition(Position::LEFT);
   
   
  linea1.attach_function(1, fn_inicio); 
  linea2.attach_function(1, fn_perfiles); 
  linea3.attach_function(1, fn_cucharada);
  linea4.attach_function(1, fn_recogida);
  
  menu.add_screen(pantalla1);
  

  
  linea1_2.set_focusPosition(Position::LEFT); 
  linea2_2.set_focusPosition(Position::LEFT); 
  linea3_2.set_focusPosition(Position::LEFT); 
  
  linea1_2.attach_function(1, fn_perfil1); 
  linea2_2.attach_function(1, fn_perfil2);
  linea3_2.attach_function(1, fn_atras);
   
  menu.add_screen(pantalla2);

  linea1_3.set_focusPosition(Position::LEFT); 
  linea2_3.set_focusPosition(Position::LEFT); 
  linea3_3.set_focusPosition(Position::LEFT); 
  
  linea1_3.attach_function(1, fn_activar); 
  linea2_3.attach_function(1, fn_modificar);
  linea3_3.attach_function(1, fn_atras2);
   
  menu.add_screen(pantalla3); 

  linea1_4.set_focusPosition(Position::LEFT); 
  linea2_4.set_focusPosition(Position::LEFT); 
  linea3_4.set_focusPosition(Position::LEFT); 
  
  linea1_4.attach_function(1, fn_altura); 
  linea2_4.attach_function(1, fn_giro);
  linea3_4.attach_function(1, fn_atras3);
   
  menu.add_screen(pantalla4);

  

  linea1_5.set_focusPosition(Position::LEFT); 
  linea2_5.set_focusPosition(Position::LEFT); 
  linea3_5.set_focusPosition(Position::LEFT); 

  linea1_5.attach_function(1, fn_aumento); 
  linea2_5.attach_function(1, fn_disminuye);
  linea3_5.attach_function(1, fn_atras4);
  
  
  menu.add_screen(pantalla5);
  
  pantalla1.set_displayLineCount(2);
  pantalla2.set_displayLineCount(2);
  pantalla3.set_displayLineCount(2);
  pantalla4.set_displayLineCount(2);
  
  menu.set_focusedLine(0);

  menu.update();
}
void loop() {

  selectOption();

  aState = digitalRead(outputA); 
    if (aState != aLastState){     
      if (digitalRead(outputB) != aState) {
        incremento++;
        if (incremento>1){
          incremento=0;
        menu.switch_focus(false);}
      } else {
        incremento++;
        if (incremento>1){
          incremento=0;
        menu.switch_focus(true);}
      }
      menu.update();
      aLastState = aState;
  }

}





//Funciones:::::
void selectOption(){
  if(digitalRead(sw) == LOW){
      Serial.println("boton");
      menu.call_function(1);
      delay(500);
  }
}

void fn_inicio(){
//  menu.change_screen(2);
//  menu.set_focusedLine(0);
//  led_seleccionado = 1;

 poss_inicial_1AB=210;
 poss_final_1AB=128;
 poss_inicial_2AB=230;
 poss_final_2AB=180;

// if(Serial1.available()){
//  fcarrera = Serial1.read(); //leemos bus serie del dato enviado
//  Serial1.println(fcarrera);
  while(fcarrera == HIGH){
   dato=2730;
   Serial1.write(dato);
   }
//  if (fcarrera == '0'){
//    digital.write(fcarrera);
//    dato = 2730;
//    Serial1.write(dato); //escribimos dato 
//    }
//    if(fcarrera == '1'){
//      articulacion_2();
//      articulacion_1();
//      }
//    }
}

Gracias de antemano.

Cuando usas SoftwareSerial en un UNO lo haces para poder monitorear lo que hace el UNO por el puerto Serie hardware que tu estas usando en tu código.
Para ello se define un puerto asi

#include <SoftwareSerial.h>

const byte rxPin = 2;
const byte txPin = 3;
// Set up a new SoftwareSerial object
SoftwareSerial mySerial (rxPin, txPin);

Aca le estoy diciendo que use los pines 2 y 3 como RX y TX de un puerto que llamo mySerial.
tu código en el UNO cambiaría asi

#define EN 8

//Direction pin
#define X_DIR 6

//Step pin
#define X_STP 3

#include <SoftwareSerial.h>

const byte rxPin = 2;
const byte txPin = 3;
// Set up a new SoftwareSerial object
SoftwareSerial mySerial (rxPin, txPin);

//A498
int delayTime = 600;
int stps            = 2730;

int dato;
byte fcarrera;


void step(boolean dir, byte dirPin, byte stepperPin, int steps) {
  digitalWrite(dirPin, dir);
  delay(100);
  for (int i = 0; i< steps; i++)   {
    digitalWrite(stepperPin, HIGH);
    delayMicroseconds(delayTime);
    digitalWrite(stepperPin, LOW);
    delayMicroseconds(delayTime);
  }
}

void setup() {
  Serial.begin(9600);
  mySerial.begin(9600);
  pinMode(X_DIR, OUTPUT); pinMode(X_STP,OUTPUT);
  pinMode(EN, OUTPUT);
  pinMode(fcarrera,INPUT);
  digitalWrite(EN,LOW);
  digitalWrite(fcarrera,LOW);
}
void loop() {
 
  //si existe datos disponibles en el bus serial 
  if (mySerial.available()>0){
     dato = mySerial.read(); // leemos dato de los pines 2 y 3
     Serial.println(dato);   // imprimo lo recibido por el puerto serie del UNO
     if (dato =! stps){
        step(false, X_DIR, X_STP, stps);
        delay(1000);  // <========= elimina siempre retardos cuando uses puertos serie
    }
    if (dato == stps){
      step(true, X_DIR, X_STP, stps);
      delay(1000);   // <========= elimina siempre retardos cuando uses puertos serie
      }
    }
}

El Mega tiene 4 puertos serie hardware asi que no tiene porque usar SoftwareSerie
En el MEGA usas Serial1. Compruebo tu código.

Tienes una gran mezcla.
Defines Serial1.begin() pero no defines Serial.begin por lo tanto jamás va a funcionar.
Serial deberías dejarlo como en el UNO para tareas de monitoreo.
Serial1 para comunicación con el UNO via pines 2 y 3 porque no tiene mas que 1 puerto Serie.

Corrijo el código del MEGA y lo posteo.
El código jamas funcionará.
Tienes atada la consulta del puerto serie (y ademas esta mal) a una función del menú.
Las dos rutinas serie en el UNO y en el MEGA deben estar en el loop sin ataduras. Tal vez condicionadas por algun switch si fuera el caso pero cuanto mas directas esten mejor.

El UNO manda datos si el interruptor esta en ALTO por lo tanto en el MEGA siempre debe estar escuchando si eso ocurrió y no tenerlo supeditado a una función del menú.

1 Like

vale, muchas gracias!

No entiendo que puede tener que ver la comunicación con un interruptor o pulsador como un fin de carrera a menos que la condiciones a su accionamiento o no.
En el UNO nada la condiciona. Tienes comunicación siempre.
En el MEGA parece que si pero como dije, confundes para que sirve un menu con una comunicación serie.

Un menú es algo que te permite configurar cosas.
La comunicaicón serie deberia estar funcionando siempre y solo reaccionar a ciertos eventos.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.