Un ROV de agua dulce, con mando de PS2

Si te gustan los modelos Radio Control RC este es tu foro.
asesorplaza1
Colaborador
Colaborador
Mensajes: 209
Registrado: Jue Ene 24, 2019 6:51 am
Ubicación: Cuenca

Re: Un ROV de agua dulce, con mando de PS2

Mensaje por asesorplaza1 »

Buenas tardes.

Ahora que sabéis como se comunican los Arduinos, vamos a darle otra vuelta a la tuerca, y a complicar un poco más la cosa.

Si todavía se puede complicar mucho más, quien dijo que esto era fácil.

Vale que comunicar dos Arduinos encima de la mesa, no tiene mucho sentido, pero a lo mejor, si os animáis y os hacéis un barco con muchos complementos, a lo mejor si va cogiendo sentido la cosa, que un Arduino se encargue del control, y el otro Arduino de la ejecución de las ordenes.

Pero esa no es la finalidad, la finalidad como siempre es sentar la base para poder subir un escalón en esta escalera sin final, que es el ecosistema Arduino.

Qué pasaría si os digo, que la comunicación por cable, no se queda encima de la mesa, que puedes comunicar dos Arduinos a una distancia de 1.200 metros, si lo he puesto bien 1.2 Km.

Alguno pensareis que se me ha ido la cabeza, y otros pensareis que como es posible eso. Pues es posible como casi todo en Arduino, con un poco de ayuda.

En este caso la ayuda la da el modulo RS485, y vamos a ver como se hace. Primero de una manera sencilla, en esta pagina

https://arduinoinfo.mywikis.net/wiki/So ... 485Example

Y luego de una manera, un poco más técnica, en esta otra página.

https://proyectoarduino.com/comunicaciones-con-rs485/

No me canso de repetirlo

Que quede claro que yo no tengo nada que ver con la página, ni con ninguno de los productos a los que se hace referencia en su página, así como con ninguna otra página de Internet, a la que pueda hacer referencia en esta publicación. Solamente la considero como una buena pagina de referencia y consulta, para resolver muchas dudas que nos puedan surgir.

Un saludo.
asesorplaza1
Colaborador
Colaborador
Mensajes: 209
Registrado: Jue Ene 24, 2019 6:51 am
Ubicación: Cuenca

Re: Un ROV de agua dulce, con mando de PS2

Mensaje por asesorplaza1 »

Buenas noches.

Pues ahora que sabemos cómo comunicar dos Arduinos por cable a una distancia de hasta 1.2 Km., vamos a hacer magia y vamos a cortar el cable.

SUELTA LAS TIJERAS, no se te ocurra cortar ningún cable, he dicho que vamos a hacer magia, no que vamos a cortar nada.

Bueno no es tan sencillo, realmente no vamos a cortar el cable, si no que vamos a utilizar otro procedimiento, para conseguir la comunicación entre los Arduinos de manera inalámbrica.

Esto ya os gusta más eh, seguro que a más de uno se le han abierto los ojos, y se le han puesto como platos.

Voy a presentaros el modulo de comunicación inalámbrica nRF24L01, desde la pagina del amigo Don Luis Llamas.

https://www.luisllamas.es/comunicacion- ... -nrf24l01/

Estos módulos son los que se utilizan para controlar los drones. Seguro que alguno habrá pensado, “Has dicho drones, ya no me interesa.”

Ya os he comentado, que tenemos que ampliar el campo de visión, y lo que se puede utilizar en un AUDI, porque no utilizarlo en un MERCEDES, si en definitiva los dos son coches, pues vamos a aprovecharnos de que los drones están de moda, y han bajado considerablemente el precio de los componentes electrónicos, para así poder utilizarlo en los barcos.

En esta página, también se explica cómo funciona el módulo nRF24L01

https://naylampmechatronics.com/blog/16 ... duino.html

Ya sabéis que no me gusta poner paginas de tiendas, si no es porque explican cómo funciona el módulo, o sensor, de una manera un poco especial.


A partir de ahora, vamos a ir mezclando los ingredientes que hemos visto hasta ahora, y en este caso, vamos a juntar, el Arduino como no, el mando de la PS2, y vamos a utilizar un módulo nuevo de radio frecuencia a 2.4 Ghz, el modulo se llama nRF24L01.

Vamos a ver en esta página como se hace una radio de 16 canales y 2.4 Ghz, de bajo presupuesto, no es para ganar ningún concurso de exclusividad, ni de como llamar la atención, si no de una emisora barata y muy funcional.

Dejamos para los concursos de belleza, esas emisoras de dos mil Euros, y lo las menospreciamos, y a demás las seguimos mirando con envidia insana, y pensando, “Que habrá hecho ese manazas para poder manejar ese tesoro, que encima no tiene cuidado con ella, y se la va a cargar.”

Pero como no queremos renunciar a poder manejar los mismos 16 canales y a la misma frecuencia 2.4 Ghz, nos hacemos nosotros mismos la emisora, siguiendo los pasos de esta página.

http://electrotuto.com/2014/10/09/reali ... -nrf24l01/

No quiero ser pesado, pero esto ya es de ser cansino, para evitar problemas de derechos de autor y demás, pongo la coletilla de siempre, aunque ya estoy arto de escribirla.

Que quede claro que yo no tengo nada que ver con la página, ni con ninguno de los productos a los que se hace referencia en su página, así como con ninguna otra página de Internet, a la que pueda hacer referencia en esta publicación. Solamente la considero como una buena pagina de referencia y consulta, para resolver muchas dudas que nos puedan surgir.

Un saludo.
asesorplaza1
Colaborador
Colaborador
Mensajes: 209
Registrado: Jue Ene 24, 2019 6:51 am
Ubicación: Cuenca

Re: Un ROV de agua dulce, con mando de PS2

Mensaje por asesorplaza1 »

Buenas tardes.

Bueno, pues parece que esto va tomando forma, y he averiguado varias cosas.

Como ya os he comentado, estoy registrado en un foro de construcción de ROV, con proyectos similares al mío, y tengo un tema abierto en este enlace.

http://www.homebuiltrovs.com/rovforum/v ... =18&t=1908

Es un coñazo, tener que escribir las preguntas en Español, y luego traducirlas al Inglés, menos mal que lo hago con el traductor de BING, pero aun así, es un lio, porque traduce lo que quiere y como quiere, y tengo que estar traduciendo y volviendo a traducir las frases, para comprobar que tengan sentido, pero bueno, a pesar de las dificultades he conseguido varios progresos.

El Americano que me está ayudando, Bigbadbob, después de mucho comentar como mejorar el programa, ha llegado a la conclusión de que el Arduino se hace un lio al tener que utilizar los dos Puertos Serie, a la vez que el bus SPI para controlar el mando, por lo tanto la mejor solución a la que hemos llegado, es que hay que separar lo que hasta ahora tenía como “Código Maestro”, en dos partes y en dos Arduinos, una parte del código en un Arduino que solo controle el mando, y otra parte del código que controle los sensores y mande los datos, de momento al ordenador, y después a la pantalla Nextion, en otro programa y en otro Arduino.

Como no se puede utilizar la Comunicación Serie, con la impresión de datos y con el mando de la PS2, todo junto, en un mismo programa y en un solo Arduino, por lo tanto, tengo que utilizar tres Arduinos, dos en el puesto de control, y uno dentro del ROV, y a demás así es como lo tiene el montado, después de un montón de tiempo intentando hacerlo de otras formas, y no sacando nada diferente en claro.

El sistema funciona de la siguiente manera.

El Arduino que está dentro del ROV, controla los sensores y solo manda por el puerto TX los datos a un Arduino, que está en el puesto de control, que los recibe por el puerto RX, los interpreta y los manda a la pantalla.

A su vez el mismo Arduino que está dentro del ROV, por el puerto RX, solo recibe los datos del mando PS2, y ejecuta las ordenes del mando.

Es un poco más lioso pero es la única manera de que funcione, pongo una foto para que veáis que no es tan complicado como resulta explicarlo escribiendo.
Diagrama conexiones.jpg
Diagrama conexiones.jpg (70.05 KiB) Visto 2476 veces
La foto no es para ganar un premio Pulitzer, pero se ve lo que os quiero decir.

Un saludo
Adjuntos
51_con_3_Arduinos_15_05_2020.rar
(15.64 KiB) Descargado 96 veces
Avatar de Usuario
tsanshon
Colaborador
Colaborador
Mensajes: 169
Registrado: Mié Jul 29, 2009 1:36 am
Ubicación: Bilbao

Re: Un ROV de agua dulce, con mando de PS2

Mensaje por tsanshon »

Hola AP1.

La opción de usar 4 controladores y comunicación unidireccional es igualmente válida. Como ventajas: tienes 4 programas mas pequeños que son mas fáciles de depurar. Como inconveniente pasa de tener 2 programas a 4, todo el hardware se hace mas complejo, vas a gastar más batería, es mas caro...

Te puedo asegurar por propia experiencia que se puede hacer con un maestro y un esclavo.
El remolcador Gatika, lleva un Arduino mega en en control remoto y otro el el barco. El del control remoto usa tres puertos serial: uno para el modulo de radiofrecuencia, otro para la pantalla táctil y otro para las luces de los pulsadores. El del barco usa los cuatro puertos serie: uno para el módulo de radiofrecuencia, otro para el controlador de servos, otro para las luces y el cuarto para telemetría.

Durante la programación del Damen multi cat 1205 también tuve bastantes problemas con la comunicación hasta que di con una secuencia para sincronizar la comunicación.
La idea es que el esclavo solo enviá un mensaje cada vez que recibe uno del maestro, de esta forma enviando periódicamente un mensaje al esclavo desde el maestro la comunicación se mantiene sincronizada.


Intentare describirla adaptada a tu ROV.

Las tareas básicas del maestro:
A.- Leer el estado del mando PS2 y enviarlo al esclavo.
B.- Presentar en pantalla los datos recibidos del esclavo.
Y las del esclavo:
C.- Actualizar el estado de los motores y luces con los datos recibidos del maestro.
D.- Enviar datos de los sensores al maestro

La secuencia es: A; C; D; B y se ejecuta cada 10 veces por segundo.

Paso 1: A. El maestro comprueba si hay cambios en los mandos diez veces por segundo (cada 100milisegundos) utilizando la función millis().
(https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay)
Para ello defino una variable y la inicializo: unsigned long a = millis(); fuera de loop().
Dentro de loop() compruebo si han pasado mas de 100 milisegundos

if (milis() > a+100) {
// Aquí el código que lee el estado de los mandos.
ETout.sendData(); // Código para enviar el menaje al esclavo
a = millis(); // Actualiza en valor de a (resetea el temporizador)
}

Paso 2: C y D. El esclavo recibe el mensaje, actualiza el estado de motores etc. y enviá datos al maestro.
if (ETin.receiveData()){
// Aqui el código para actualizar el estado de motores, luces...
ETout.sendData (); // Envía los datos al puerto serie para el ROV Arduino
}

Paso 3: B. El maestro recibe el mensaje del esclavo y presenta los datos en pantalla.

if (ETin.receiveData()) {
// Código para presentar datos en pantalla
}

El codigo del maestro quedaría asi:

unsigned long a = millis();
void setup(){}
void loop(){
if (milis() > a+100) {
// Aqui el código que lee el estado de los mandos.
ETout.sendData (); // Código para enviar el menaje al esclavo
a = millis(); // Actualiza en valor de a (resetea el temporizador)
}

if (ETin.receiveData()) {
// Código para presentar datos en pantalla
}
}

El del esclavo:

void setup(){}
void loop(){
if (ETin.receiveData()){
// Aqui el código para actualizar el estado de motores, luces...
// Envia mensaje con valores de los sensores
ETout.sendData (); // Envía los datos al puerto serie para el ROV Arduino
}
}

Importante: Como el Serial esta conectado al puerto USB y lo usamos para el monitor serial. Asegurate de que la comunicación entre los Arduinos se hace con un serial distinto (serial1, 2 ó 3) tanto en el programa como las conexiones del cableado.


Espero que te sirva de ayuda.

Un saludo.
Alberto.
asesorplaza1
Colaborador
Colaborador
Mensajes: 209
Registrado: Jue Ene 24, 2019 6:51 am
Ubicación: Cuenca

Re: Un ROV de agua dulce, con mando de PS2

Mensaje por asesorplaza1 »

Buenas tardes.

Lo primero que tengo que hacer es darle las gracias a Tsanahon, por su respuesta.

Muchas gracias Alberto.

Y ahora voy a intentar implementar sus consejos en el programa del ROV.

Ya sabia yo que pasaba algo raro, pero no sabia lo que era, ni daba con la solución.

Muchas gracias, un saludo.
asesorplaza1
Colaborador
Colaborador
Mensajes: 209
Registrado: Jue Ene 24, 2019 6:51 am
Ubicación: Cuenca

Re: Un ROV de agua dulce, con mando de PS2

Mensaje por asesorplaza1 »

Código maestro

Código: Seleccionar todo

#include <PS2X_lib.h> // Librería PS2 de Bill Porter
#include <EasyTransfer.h> // Librería Easy Transfer de Bill Porter

PS2X ps2x;         // Crea la clase del controlador PS2
int error = 0;     // Crea la clase de error del mando
byte type = 0;     // Crea el tipo de error del mando
byte vibrate = 0;  // Crea la vibracion del mando

EasyTransfer ETin, ETout;  //Cree los objetos de EasyTransfer para la comunicación bidireccional

const int grnLEDpin = 30;       // LED verde    esta encendido en pin Digital 4
const int redLEDpin = 31;       // LED rojo     esta encendido en pin Digital 3
const int yelLEDpin = 32;       // LED amarillo esta encendido en pin Digital 2
const int VwarnLEDpin = 33;     // LED de advertencia de voltaje esta encendido en el Pin digital D5
const int TwarnLEDpin = 34;     // LED de advertencia de temperatura esta encendido en el pin D6
const int pinLedColision = 35;  // LED de advertencia de peligro colisión en el pin 27
const int LowBatVolts10 = 96;   // esto es para mantener el valor de advertencia de voltaje de bateria bajo en el umbral de x10.

int ForwardVal = 0;             // valor leído en palo PS2 derecho arriba/abajo
int YawLeftVal = 0;             // valor leído en palo PS2 derecho derecha/izquierda
int UpVal = 0;                  // valor leído en palo PS2 izquierdo arriba/abajo
int RollLeftVal = 0;            // valor leído en palo PS2 izquierdo derecha/izquierda

boolean PSB_PAD_UPstate = false;     // Genera variable para guardar y mandar los datos del botón Izquierda arriba al Esclavo
boolean PSB_PAD_DOWNstate = false;   // Genera variable para guardar y mandar los datos del botón Izquierda abajo al Esclavo
boolean PSB_PAD_LEFTstate = false;   // Genera variable para guardar y mandar los datos del botón Izquierda izquierdo al Esclavo
boolean PSB_PAD_RIGHTstate = false;  // Genera variable para guardar y mandar los datos del botón Izquierda derecho al Esclavo
boolean PSB_BLUEstate = false;       // Genera variable para guardar y mandar los datos del botón Cruz azul al Esclavo
boolean PSB_GREENstate = false;      // Genera variable para guardar y mandar los datos del botón Triangulo verde al Esclavo
boolean PSB_PINKstate = false;       // Genera variable para guardar y mandar los datos del botón Cuadrado rosa al Esclavo
boolean PSB_REDstate = false;        // Genera variable para guardar y mandar los datos del botón Circulo rojo al Esclavo
boolean PSB_L1state = false;         // Genera variable para guardar y mandar los datos del botón Izquierda delante arriba al Esclavo
boolean PSB_L2state = false;         // Genera variable para guardar y mandar los datos del botón Izquierda delante abajo al Esclavo
boolean PSB_L3state = false;         // Genera variable para guardar y mandar los datos del botón Palo izquierdo abajo al Esclavo
boolean PSB_R1state = false;         // Genera variable para guardar y mandar los datos del botón Derecha delante arriba al Esclavo
boolean PSB_R2state = false;         // Genera variable para guardar y mandar los datos del botón Derecha delante abajo al Esclavo
boolean PSB_R3state = false;         // Genera variable para guardar y mandar los datos del botón Palo derecho abajo al Esclavo

float ROVTMP = 0;                                  // Variable para recibir los datos de la temperatura interior del ROV
float ROVTMP1 = 0;                                 // Variable para recibir los datos de la temperatura motor derecho del ROV
float ROVTMP2 = 0;                                 // Variable para recibir los datos de la temperatura motor izquierdo del ROV
float ROVDHThumid;                                 // Variable para recibir los datos de la humedad interior del ROV
float ROVDHThumid1;                                // Variable para recibir los datos de la humedad del motor derecho del ROV
float ROVDHThumid2;                                // Variable para recibir los datos de la humedad del motor izquierda del ROV
float AccX, AccY, AccZ, Temp, GyroX, GyroY, GyroZ; // Variable para recibir los datos del Giroscopio del ROV
float E18D80NK;                                    // Variable para recibir los datos del sensor E18D80NK del ROV
float sensorDS18B20;                               // Variable para recibir los datos del sensor DS18B20 del ROV
float pressure_bar;                                // Variable para recibir los datos del sensor de presión interior SKU237545 en Bares del ROV
float pressure_psi;                                // Variable para recibir los datos del sensor de presión interior SKU237545 en PSI del ROV
float pressure_bar1;                               // Variable para recibir los datos del sensor de presión exterior SKU237545 en Bares del ROV
float pressure_psi1;                               // Variable para recibir los datos del sensor de presión interior SKU237545 en PSI del ROV
float ROVDepth;                                    // Variable para recibir los datos de la profundidad a la que se encuentra el ROV
float ROVHDG;                                      // Variable para recibir los datos de la dirección del ROV en grados

struct RECEIVE_DATA_STRUCTURE  // estructura de mensaje de datos recibidos de los sensores
{
  int BattVolt;             // Recibe mensaje de voltaje de batería
  int t;                    // Recibe mensaje de temperatura interior del ROV
  int t1;                   // Recibe mensaje de temperatura del motor derecho
  int t2;                   // Recibe mensaje de temperatura del motor izquierdo
  int ROVDepth;             // Recibe mensaje de lectura de profundidad de ROV (m)
  int ROVHDG;               // Recibe mensaje de Dirección del ROV (grados)
  int h;                    // Recibe mensaje de humedad del interior del ROV
  int h1;                   // Recibe mensaje de humedad del motor derecho
  int h2;                   // Recibe mensaje de humedad del motor izquierdo
  int AccX;                 // Recibe mensaje de datos de inclinación del eje X
  int AccY;                 // Recibe mensaje de datos de inclinación del eje Y
  int AccZ;                 // Recibe mensaje de datos de inclinación del eje Z
  int Temp;                 // Recibe mensaje de datos de temperatura del giroscopio
  int GyroX;                // Recibe mensaje de datos de aceleración en el eje X
  int GyroY;                // Recibe mensaje de datos de aceleración en el eje Y
  int GyroZ;                // Recibe mensaje de datos de aceleración en el eje Z
  int E18D80NK;             // Recibe mensaje de lectura del sensor infrarrojo E18-D80NK
  int pinLedColision;       // Recibe mensaje de encender alarma de colisión
  int sensorDS18B20;        // Recibe mensaje de lectura del sensor de temperatura DS18B20
  int pressure_bar;         // Recibe mensaje de lectura del sensor de presión SKU237545 en Bares
  int pressure_psi;         // Recibe mensaje de lectura del sensor de presión SKU237545 en PSI
  int pressure_bar1;        // Recibe mensaje de lectura del sensor de presión SKU237545 Interno en Bares
  int pressure_psi1;        // Recibe mensaje de lectura del sensor de presión SKU237545 Interno en PSI
};

struct SEND_DATA_STRUCTURE  // estructura de mensaje de datos enviados
{
  int upLraw = 0;  //Variables para transportar los datos reales sin procesar de los ESCs
  int upRraw = 0;
  int HLraw = 0;
  int HRraw = 0;
  volatile boolean PSB_PAD_UPstate;     // Manda lectura del botón Izquierda arriba al Esclavo
  volatile boolean PSB_PAD_DOWNstate;   // Manda lectura del botón Izquierda abajo al Esclavo
  volatile boolean PSB_PAD_RIGHTstate;  // Manda lectura del botón Izquierda derecho al Esclavo
  volatile boolean PSB_PAD_LEFTstate;   // Manda lectura del botón Izquierda Izquierda al Esclavo
  volatile boolean PSB_BLUEstate;       // Manda lectura del botón Cruz azul al Esclavo
  volatile boolean PSB_GREENstate;      // Manda lectura del botón Triangulo verde al Esclavo
  volatile boolean PSB_PINKstate;       // Manda lectura del botón Cuadrado rosa al Esclavo
  volatile boolean PSB_REDstate;        // Manda lectura del botón Circulo rojo al Esclavo
  volatile boolean PSB_L1state;         // Manda lectura del botón Izquierda delante arriba al Esclavo
  volatile boolean PSB_L2state;         // Manda lectura del botón Izquierda delante abajo al Esclavo
  volatile boolean PSB_L3state;         // Manda lectura del botón Palo izquierdo abajo al Esclavo
  volatile boolean PSB_R1state;         // Manda lectura del botón Derecha delante arriba al Esclavo
  volatile boolean PSB_R2state;         // Manda lectura del botón Derecha delante abajo al Esclavo
  volatile boolean PSB_R3state;         // Manda lectura del botón Palo derecho abajo al Esclavo
  volatile boolean LEDHdlts;            // Manda que hacer con los Focos, encendidos/apagados
};

//dar un nombre al grupo de datos
RECEIVE_DATA_STRUCTURE rxdata;
SEND_DATA_STRUCTURE txdata;

unsigned long a = millis();  // Se define y se inicia una variable llamada millis

void setup()
{

  Serial.begin(9600);      // Comienza la Comunicación en Serie para hablar con el ordenador a 9600 Baudios
  Serial1.begin(9600);    // Comienza la comunicación Serie en el puerto 1, pines 18 y 19, para hablar con el Arduino Esclavo
  Serial1.flush();         // Depura la información del Puerto Serie
  ETin.begin(details(rxdata), &Serial1);    // Comienza la recepción de datos a través de Serial, en los pines 18 y 19
  ETout.begin(details(txdata), &Serial1);   // Comienza el envío de datos a través de Serial, en los pines 18 y 19

  pinMode(grnLEDpin, OUTPUT);  //se establece grnLEDpin como salida
  pinMode(redLEDpin, OUTPUT);  //se establece redLEDpin como salida
  pinMode(yelLEDpin, OUTPUT);  //se establece yelLEDpin como salida
  pinMode(VwarnLEDpin, OUTPUT);  //se establece el pin de advertencia de batería baja como salida
  pinMode(TwarnLEDpin, OUTPUT);  //se establece el pin de sobre temperatura como salida

  // Pines y ajustes de configuración: GamePad(clock, command, attention, data, Pressures?, Rumble?)
  error = ps2x.config_gamepad(22, 23, 24, 25, false, false);

  if (error == 0)
  {
    Serial.println (F("\n Controlador encontrado y configurado con éxito"));
  }

  else if (error == 1)
    Serial.println (F(" \n No se encontró el controlador, verifique el cableado, consulte readme.txt para habilitar la depuración. Visite www.billporter.info para obtener sugerencias para la solución de problemas"));

  else if (error == 2)
    Serial.println (F(" \n El controlador se encontró, pero no admite comandos. Consulte readme.txt para habilitar la depuración. Visite www.billporter.info para obtener sugerencias para la solución de problemas"));

  else if (error == 3)
    Serial.println (F(" \n El controlador se niega a ingresar en el modo de presiones, puede que no lo admita"));

  // Serial.print(ps2x.Analog(1), HEX);
  type = ps2x.readType();
}

void loop()
{

  if (millis() > a + 100) {


    if (error == 0)
    {
      // Controlador DualShock
      ps2x.read_gamepad();

      //lecturas analógicas del palo
      //traduce las lecturas del palo al las instrucciones del ESC
      //las lecturas de los palos del controlador PS2 son de 0 a 255
      //con el neutro en 128. Las posiciones cero son
      //a la izquierda para movimientos del eje X y arriba para los movimientos del eje Y

      ForwardVal = ps2x.Analog(PSS_RY);
      YawLeftVal = ps2x.Analog(PSS_RX);
      UpVal = ps2x.Analog(PSS_LY);
      RollLeftVal = ps2x.Analog(PSS_LX);

      // Lectura de todos los botones del mando
      // Esto será verdad hasta que algún botón cambie de estado, (activado / desactivado)
      if (ps2x.NewButtonState())
      {
        if (ps2x.ButtonPressed(PSB_PAD_UP))                // Lee el valor del botón Izquierda arriba al Esclavo
        {
          PSB_PAD_UPstate = (!PSB_PAD_UPstate);            // Guarda el dato del botón en su variable
          digitalWrite(yelLEDpin, PSB_PAD_UPstate);        // Enciende el LED Amarillo
        }
        txdata.PSB_PAD_UPstate = (PSB_PAD_UPstate);        // Manda el estado del botón al Esclavo

        if (ps2x.ButtonPressed(PSB_PAD_DOWN))              // Lee el valor del botón Izquierda abajo al Esclavo
        {
          PSB_PAD_DOWNstate = (!PSB_PAD_DOWNstate);            // Guarda el dato del botón en su variable
          digitalWrite(yelLEDpin, PSB_PAD_DOWNstate);      // Enciende el LED Amarillo
        }
        txdata.PSB_PAD_DOWNstate = (PSB_PAD_DOWNstate);    // Manda el estado del botón al Esclavo

        if (ps2x.ButtonPressed(PSB_PAD_RIGHT))             // Lee el valor del botón Izquierda derecho al Esclavo
        {
          PSB_PAD_RIGHTstate = (!PSB_PAD_RIGHTstate);      // Guarda el dato del botón en su variable
          digitalWrite(yelLEDpin, PSB_PAD_RIGHT);          // Enciende el LED Amarillo
        }
        txdata.PSB_PAD_RIGHTstate = (PSB_PAD_RIGHTstate);  // Manda el estado del botón al Esclavo

        if (ps2x.Button(PSB_PAD_LEFT))                     // Lee el valor del botón Izquierda Izquierda al Esclavo
        {
          PSB_PAD_LEFTstate = (!PSB_PAD_LEFTstate);        // Lectura del estado del botón
          txdata.LEDHdlts = PSB_PAD_LEFTstate;             // Guarda que hacer con el estado de los focos, encendido / apagado
          digitalWrite(yelLEDpin, PSB_PAD_LEFTstate);      // Enciende el Led Amarillo
          Serial.print (F("\n Focos apagados"));           // Imprime la frase "Focos apagados"
        }
        else if (!txdata.LEDHdlts)
        {
          digitalWrite(yelLEDpin, LOW);                    // Apaga el led amarillo
          Serial.print (F("\n Focos encendidos"));         // Imprime la frase " Focos encendidos"
        }

        txdata.PSB_PAD_LEFTstate = (PSB_PAD_LEFTstate);    // Manda el estado del botón al Esclavo

        if (ps2x.ButtonPressed(PSB_BLUE))                  // Lee el valor del botón Cruz azul al Esclavo
        {
          PSB_BLUEstate = (!PSB_BLUEstate);                // Guarda el dato del botón en su variable
          digitalWrite(yelLEDpin, PSB_BLUEstate);          // Enciende el Led Amarillo
        }
        txdata.PSB_BLUEstate = (PSB_BLUEstate);            // Manda el estado del botón al Esclavo

        if (ps2x.ButtonPressed(PSB_GREEN))                 // Lee el valor del botón Triangulo verde al Esclavo
        {
          PSB_GREENstate = (!PSB_GREENstate);              // Guarda el dato del botón en su variable
          digitalWrite(yelLEDpin, PSB_GREENstate);         // Enciende el LED Amarillo
        }
        txdata.PSB_GREENstate = (PSB_GREENstate);          // Manda el estado del botón al Esclavo

        if (ps2x.ButtonPressed(PSB_PINK))                  // Lee el valor del botón Cuadrado rosa al Esclavo
        {
          PSB_PINKstate = (!PSB_PINKstate);                // Guarda el dato del botón en su variable
          digitalWrite(yelLEDpin, PSB_PINKstate);          // Enciende el LED Amarillo
        }
        txdata.PSB_PINKstate = (PSB_PINKstate);            // Manda el estado del botón al Esclavo

        if (ps2x.ButtonPressed(PSB_RED))                   // Lee el valor del botón Circulo rojo al Esclavo
        {
          PSB_REDstate = (!PSB_REDstate);                  // Guarda el dato del botón en su variable
          digitalWrite(yelLEDpin, PSB_REDstate);           // Enciende el LED Amarillo
        }
        txdata.PSB_REDstate = (PSB_REDstate);              // Manda el estado del botón al Esclavo

        if (ps2x.ButtonPressed(PSB_L3))                    // Lee el valor del botón Palo izquierdo abajo al Esclavo
        {
          PSB_L3state = (!PSB_L3state);                    // Guarda el dato del botón en su variable
          digitalWrite(yelLEDpin, PSB_L3state);            // Enciende el Led Amarillo
        }
        txdata.PSB_L3state = (PSB_L3state);                // Manda el estado del botón al Esclavo

        if (ps2x.ButtonPressed(PSB_R1))                    // Lee el valor del botón Derecha delante arriba al Esclavo
        {
          PSB_R1state = (!PSB_R1state);                    // Guarda el dato del botón en su variable
          digitalWrite(yelLEDpin, PSB_R1state);            // Enciende el Led Amarillo
        }
        txdata.PSB_R1state = (PSB_R1state);                // Manda el estado del botón al Esclavo

        if (ps2x.ButtonPressed(PSB_R2))                    // Lee el valor del botón Derecha delante abajo al Esclavo
        {
          PSB_R2state = (!PSB_R2state);                    // Guarda el dato del botón en su variable
          digitalWrite(yelLEDpin, PSB_R2state);            // Enciende el Led Amarillo
        }
        txdata.PSB_R2state = (PSB_R2state);                // Manda el estado del botón al Esclavo

        if (ps2x.Button(PSB_R3))                           // Lee el valor del botón Palo derecho abajo al Esclavo
        {
          PSB_R3state = (!PSB_R3state);                    // Guarda el dato del botón en su variable
          digitalWrite(yelLEDpin, PSB_R3state);            // Enciende el Led Amarillo
        }
        txdata.PSB_R3state = (PSB_R3state);                // Manda el estado del botón al Esclavo

        if (ps2x.ButtonPressed(PSB_L1))                    // Lee el valor del botón Izquierda delante arriba al Esclavo
        {
          PSB_L1state = (!PSB_L1state);                    // Guarda el dato del botón en su variable
          digitalWrite(yelLEDpin, PSB_L1state);            // Enciende el Led Amarillo
        }
        txdata.PSB_L1state = (PSB_L1state);                // Manda el estado del botón al Esclavo

        if (ps2x.ButtonPressed(PSB_L2))                    // Lee el valor del botón Izquierda delante abajo al Esclavo
        {
          PSB_L2state = (!PSB_L2state);                    // Guarda el dato del botón en su variable
          digitalWrite(yelLEDpin, PSB_L2state);            // Enciende el Led Amarillo
        }
        txdata.PSB_L2state = (PSB_L2state);                // Manda el estado del botón al Esclavo
      }

      //variables para transportar los datos en bruto reales para los ESCs y servos
      txdata.upLraw = (128 - UpVal) - (128 - RollLeftVal) / 2; //esto será hasta un valor de 192
      txdata.upRraw = (128 - UpVal) + (128 - RollLeftVal) / 2; //esto será hasta un valor de 192
      txdata.HLraw = -(128 - ForwardVal) + (128 - YawLeftVal); //esto será hasta un valor de 256
      txdata.HRraw = -(128 - ForwardVal) - (128 - YawLeftVal); //esto será hasta un valor de 256
      //escala los valores para que sean adecuados para los ESCs y para los Servos
      //estos valores podrán escribirse directamente en los  ESCs y en los Servos
      txdata.upLraw = map(txdata.upLraw, -193, 193, 0, 179);
      txdata.upRraw = map(txdata.upRraw, -193, 198, 0, 179);
      txdata.HLraw = map(txdata.HLraw, -256, 256, 0, 179);
      txdata.HRraw = map(txdata.HRraw, -256, 256, 0, 179);
    }

    // Enviar el mensaje al puerto serie para el Arduino del ROV
    ETout.sendData();

    a = millis();
  }

  if (ETin.receiveData())    // Recibe el mensaje al puerto serie para el Arduino del ROV
  {
    if (rxdata.BattVolt < LowBatVolts10)
      // el factor de 10 se incluye para coincidir con el factor 10 utilizado en el valor informado que es un int multiplicado
      // Por 10 para dar una precisión de 0.1 al valor. Tiene sentido
    {
      digitalWrite(VwarnLEDpin, HIGH);
      //si el voltaje de la batería es demasiado bajo, enciende el LED de advertencia
    }
    else
    {
      digitalWrite(VwarnLEDpin, LOW);
      //de lo contrario, si el voltaje está por encima del umbral de bajo voltaje definido
      //deje el LED apagado
    }

    ROVTMP = (rxdata.t);    // Recibe los datos del Esclavo
    ROVTMP1 = (rxdata.t1);  // Recibe los datos del Esclavo
    ROVTMP2 = (rxdata.t2);  // Recibe los datos del Esclavo
    //convierte el valor de datos 0-1024 en temperatura

    if (ROVTMP > 50 || ROVTMP1 > 50 || ROVTMP2 > 50)
    {
      // Si la temperatura de cualquiera de los sensores DHT22 es demasiado alta (más de 50 grados C)
      // enciende el LED de advertencia
      digitalWrite(TwarnLEDpin, HIGH);
      Serial.print (F(" \n TEMPERATURA ELEVADA !"));
    }
    else
    {
      digitalWrite(TwarnLEDpin, LOW);
      Serial.print (F(" \n Temperatura Normal"));
      // De lo contrario, si la temperatura interior está en un nivel aceptable
      // Deje el LED apagado y deje el relé de la bomba de refrigeración apagado
    }

    ROVDHThumid = (rxdata.h);    // Recibe los datos del Esclavo
    ROVDHThumid1 = (rxdata.h1);  // Recibe los datos del Esclavo
    ROVDHThumid2 = (rxdata.h2);  // Recibe los datos del Esclavo

    if (rxdata.E18D80NK > 0)    // Si la entrada del E18D80NK es baja, no hay ningún objeto
    {
      digitalWrite(pinLedColision, LOW);    // Apague el LED si no se detecta objeto
      Serial.print (F(" \n Todo Despejado  !"));   // manda imprimir al Monitor Serie la frase
    }
    else                                    // por el contrario, si la entrada del E18D80NK es alta
    {
      digitalWrite(pinLedColision, HIGH);   // encienda el LED de Peligro Colisión
      Serial.print (F(" \n PELIGRO Obstaculo detectado  !")); // manda imprimir la frase
    }

    ROVDepth = (rxdata.ROVDepth);             // Recibe lectura de profundidad de ROV (m)
    ROVHDG = (rxdata.ROVHDG);                 // Recibe lectura de Dirección del ROV (grados)
    AccX = (rxdata.AccX);                     // Recibe lectura de datos de inclinación del eje X
    AccY = (rxdata.AccY);                     // Recibe lectura de datos de inclinación del eje Y
    AccZ = (rxdata.AccZ);                     // Recibe lectura de datos de inclinación del eje Z
    Temp = (rxdata.Temp);                     // Recibe lectura de datos de temperatura del giroscopio
    GyroX = (rxdata.GyroX);                   // Recibe lectura de datos de aceleración en el eje X
    GyroY = (rxdata.GyroY);                   // Recibe lectura de datos de aceleración en el eje Y
    GyroZ = (rxdata.GyroZ);                   // Recibe lectura de datos de aceleración en el eje Z
    //  pinLedColision = (rxdata.pinLedColision); // Recibe lectura de encender alarma de colisión
    sensorDS18B20 = (rxdata.sensorDS18B20);   // Recibe lectura de lectura del sensor de temperatura DS18B20
    pressure_bar = (rxdata.pressure_bar);     // Recibe lectura de lectura del sensor de presión SKU237545 en Bares
    pressure_psi = (rxdata.pressure_psi);     // Recibe lectura de lectura del sensor de presión SKU237545 en PSI
    pressure_bar1 = (rxdata.pressure_bar1);   // Recibe lectura de lectura del sensor de presión SKU237545 Interno en Bares
    pressure_psi1 = (rxdata.pressure_psi1);   // Recibe lectura de lectura del sensor de presión SKU237545 Interno en PSI
    E18D80NK = (rxdata.E18D80NK);             // Recibe estado del sensor de infrarrojos


    // #if DEBUG1 { // CUIDADO CON ESTO, des comentar y cambiar 1 si imprime en Monitor Serie, 0 cero no imprime


    // A partir de aquí repito las ordenes de lcd, cambiándolas por Serial

    Serial.print (F("\n Voltaje del ROV = "));
    Serial.print (float(rxdata.BattVolt) / 10, 1);
    //factor 10 utilizado para obtener precisión adicional del valor entero y luego se muestra con 1 decimal
    Serial.print (F(" \n Temperatura del casco = "));
    Serial.print (ROVTMP);
    Serial.print (F(" *C "));
    Serial.print (F(" \n Temperatura motor DR = "));
    Serial.print (ROVTMP1);
    Serial.print (F(" *C1 "));
    Serial.print (F(" \n Temperatura motor IZ = "));
    Serial.print (ROVTMP2);
    Serial.print (F(" *C2 "));
    Serial.print (F(" \n Humedad en el interior del Casco = "));
    Serial.print (ROVDHThumid);
    Serial.print (F(" %\t"));
    Serial.print (F(" \n Humedad en el motor DR = "));
    Serial.print (ROVDHThumid1);
    Serial.print (F(" %\t"));
    Serial.print (F(" \n Humedad en el motor IZ = "));
    Serial.print (ROVDHThumid2);
    Serial.print (F(" %\t"));
    Serial.print (F(" \n Inclinación del eje X del ROV = "));
    Serial.print (AccX);
    Serial.print (F(" \n Inclinación del eje Y del ROV = "));
    Serial.print (AccY);
    Serial.print (F(" \n Inclinación del eje Z del ROV = "));
    Serial.print (AccZ);
    Serial.print (F(" \n Temperatura del Giro MPU6050 = "));
    Serial.print (Temp / 340.00 + 36.53);
    Serial.print (F(" \n Aceleración en el eje X del Giro MPU6050 = "));
    Serial.print (GyroX);
    Serial.print (F(" \n Aceleración en el eje Y del Giro MPU6050 = "));
    Serial.print (GyroY);
    Serial.print (F(" \n Aceleración en el eje Z del Giro MPU6050 = "));
    Serial.print (GyroZ);
    Serial.print (F(" \n Profundidad = "));
    Serial.print (ROVDepth);      // muestra en el Display la profundidad del ROV en metros
    Serial.print (F(" \n Direccion del ROV = "));
    Serial.print (ROVHDG);  // muestra la dirección del ROV en una brújula
    Serial.print (F(" \n Temperatura sensor DS18B20 = "));
    Serial.print (sensorDS18B20);
    Serial.print (F(" ºC"));
    Serial.print (F(" \n Valor del Sensor de Presión Interno =  "));
    Serial.print (F("   Presión en Bar = "));
    Serial.print (pressure_bar);
    Serial.print (F("    bars"));
    Serial.print (F("  || Presión en PSI = "));
    Serial.print (pressure_psi);
    Serial.print (F("    psi"));
    Serial.print (F(" \n Valor del Sensor de Presión Externo = "));
    Serial.print (F("   Presión en Bar = "));
    Serial.print (pressure_bar1);
    Serial.print (F("    bars"));
    Serial.print (F("  || Presión en PSI = "));
    Serial.print (pressure_psi1);
    Serial.print (F("    psi"));
    Serial.print (F("\n"));
  }
  // } #endif  // des comentar cuando NO quiera imprimir los Serial.print


}
asesorplaza1
Colaborador
Colaborador
Mensajes: 209
Registrado: Jue Ene 24, 2019 6:51 am
Ubicación: Cuenca

Re: Un ROV de agua dulce, con mando de PS2

Mensaje por asesorplaza1 »

Código Esclavo

Código: Seleccionar todo

// Se ponen todas las librerías juntas

#include <Servo.h>              // librería para gestionar los servos y los ESC
#include <EasyTransfer.h>       // librería Easy Transfer de Bill Porter
#include <Adafruit_Sensor.h>    // librería para gestionar el sensor de temperatura DHT22
#include <DHT.h>                // librería para el sensor DHT 22
#include <OneWire.h>            // librería para el sensor de temperatura DS18B20
#include <DallasTemperature.h>  // Librería para el sensor de temperatura DS18B20
#include <MPU6050.h>            // librería i2c para el Giroscopio ***
#include <PS2X_lib.h>           // Librería para el mando PS2
#include <ESC.h>                // Librería para los ESC

PS2X ps2x;                          // Genera un objeto llamado ps2x
EasyTransfer ETin, ETout;           // Genera los dos objetos de transferencia fácil para Comunicación bidireccional

const int pinDatosDQ = 28;                       // Pin donde se conecta el bus 1-Wire para los sensores de temperatura
OneWire oneWireObjeto(pinDatosDQ);               // Instancia a las clases OneWire y DallasTemperature
DallasTemperature sensorDS18B20(&oneWireObjeto); // Instancia a las clases OneWire y DallasTemperature

// #define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))

// Se pone toda la identificación de los DHT22 junta

DHT dht(22, DHT22);    // Seleccionamos el pin y tipo de sensor del casco
DHT dht1(24, DHT22);   // Seleccionamos el pin y tipo de sensor del motor derecho
DHT dht2(26, DHT22);   // Seleccionamos el pin y tipo de sensor del motor izquierdo

// Se pone toda la identificación de los ESC y los Servos junta

ESC ESCVL(8, 1000, 2000, 500);           // Genera objeto ESC vertical izquierdo en el pin 8, con el minimo en 1000, maximo en 2000, y armado en 500
ESC ESCVR(7, 1000, 2000, 500);           // Genera objeto ESC vertical derecho en el pin 7, con el minimo en 1000, maximo en 2000, y armado en 500
ESC ESCHL(6, 1000, 2000, 500);           // Genera Objeto ESC Horizontal Izquierdo en el pin 6, con el minimo en 1000, maximo en 2000, y armado en 500
ESC ESCHR(5, 1000, 2000, 500);           // Genera objeto ESC Horizontal Derecho, en el pin 5, con el minimo en 1000, maximo en 2000, y armado en 500
Servo ServoInmersion;           // Genera un objeto llamado ServoDireccion
int angulo = 90;                // Variable para el ángulo, inicia en 90º

// Se pone toda la identificación de los LED indicadores de batería junta

const int RedLEDpin = 13;  // El pin del indicador LED es 13.
const int HeadLts = 34;    // El control de los faros está en el pin 34
const int Voltpin = A7;    // pin analógico utilizado para leer el voltaje de la batería
const int yelLEDpin = 38;  // Pin utilizado como chivato de recibir datos del mando

// Se pone toda la identificación del sistema de refrigeración junta

const int Refrigeracion = 34; // el pin utilizado para encender la bomba de refrigeración es el 34
const int TwarnLEDpin = 36;   // El pin utilizado para el LED de alarma de temperatura es el 36

// Se pone toda la identificación del MPU6050 junta

const int MPU6050_addr = 0x68; // Direction I2C del MPU6050
int16_t AccX, AccY, AccZ, Temp, GyroX, GyroY, GyroZ;

// Se pone toda la parte de lectura de la batería junta

int volts;                          // variable para leer el voltaje del pin analógico
const float RefVolts = 5.0;         // Voltaje de referencia de la placa de 5 voltios en Nano
const float ResistFactor = 319.68;  // Calculado a partir de 1023.0 * (R2 / (R1 + R2)
// Donde R1 = 2200 ohmios y R2 = 1000 ohmios para un voltaje máximo de 15 V.

// Se pone toda la parte del sensor E18D80NK

int pinSensorE18D80NK = 30;   // Se genera el sensor E18D80NK en el pin 30
int pinLedColision = 31;      // Se genera el LED de aviso de peligro colisión en el pin 31
boolean objectDetect = false; // Marca para mostrar si se ha detectado un objeto

// Se generan todos los botones del mando

boolean PSB_PAD_UPstate = false;     // Genera el botón Izquierda arriba al Esclavo
boolean PSB_PAD_DOWNstate = false;   // Genera el botón Izquierda abajo al Esclavo
boolean PSB_PAD_LEFTstate = false;   // El botón Izquierda izquierdo ya esta usado para encender los focos
boolean PSB_PAD_RIGHTstate = false;  // Genera el botón Izquierda derecho al Esclavo
boolean PSB_BLUEstate = false;       // Genera el botón Cruz azul al Esclavo
boolean PSB_GREENstate = false;      // Genera el botón Triangulo verde al Esclavo
boolean PSB_PINKstate = false;       // Genera el botón Cuadrado rosa al Esclavo
boolean PSB_REDstate = false;        // Genera el botón Circulo rojo al Esclavo
boolean PSB_L1state = false;         // Genera el botón Izquierda delante arriba al Esclavo
boolean PSB_L2state = false;         // Genera el botón Izquierda delante abajo al Esclavo
boolean PSB_L3state = false;         // Genera el botón Palo izquierdo abajo al Esclavo
boolean PSB_R1state = false;         // Genera el botón Derecha delante arriba al Esclavo
boolean PSB_R2state = false;         // Genera el botón Derecha delante abajo al Esclavo
boolean PSB_R3state = false;         // Genera el botón Palo derecho abajo al Esclavo

// Se genera un pin de entrada de datos para el sensor de presión SKU237545

int SensorSKU237545_I = 32;  // Sensor de presión Interno
int SensorSKU237545_E = 33;  // Sensor de presión Externo

int intervalodatos = 1000;  // Hace que solo se envíen los valores 1 vez por segundo
// int auxMillis = 0;          // Indica el valor del intervalo de tiempo

// Se pone toda la estructura de recepción de datos junta

struct RECEIVE_DATA_STRUCTURE {
  int upLraw = 0;   // Variables para transportar los datos sin procesar reales de los ESC
  int upRraw = 0;
  int HLraw = 0;
  int HRraw = 0;
  volatile boolean PSB_PAD_UPstate;     // Recibe lectura del botón Izquierda arriba del Maestro
  volatile boolean PSB_PAD_DOWNstate;   // Recibe lectura del botón Izquierda abajo del Maestro
  volatile boolean PSB_PAD_RIGHTstate;  // Recibe lectura del botón Izquierda derecha del Maestro
  volatile boolean PSB_PAD_LEFTstate;   // Recibe lectura del botón Izquierda Izquierda del Maestro
  volatile boolean PSB_BLUEstate;       // Recibe lectura del botón Cruz azul del Maestro
  volatile boolean PSB_GREENstate;      // Recibe lectura del botón Triangulo verde del Maestro
  volatile boolean PSB_PINKstate;       // Recibe lectura del botón Cuadrado rosa del Maestro
  volatile boolean PSB_REDstate;        // Recibe lectura del botón Circulo rojo del Maestro
  volatile boolean PSB_L1state;         // Recibe lectura del botón Delante izquierda arriba del Maestro
  volatile boolean PSB_L2state;         // Recibe lectura del botón Delante izquierda abajo del Maestro
  volatile boolean PSB_L3state;         // Recibe lectura de presión Palo izquierda del Maestro
  volatile boolean PSB_R1state;         // Recibe lectura del botón Delante derecha arriba del Maestro
  volatile boolean PSB_R2state;         // Recibe lectura del botón Delante derecha abajo del Maestro
  volatile boolean PSB_R3state;         // Recibe lectura de presión Palo izquierdo del Maestro
  volatile boolean LEDHdlts;            // Luces LED encendidas / apagadas
};

// Se pone toda la identificación del envío de datos junta

struct  SEND_DATA_STRUCTURE {
  int BattVolt;             // Manda mensaje de datos de voltaje de batería al maestro.
  int t;                    // Manda mensaje de datos de temperatura interior del ROV al Maestro
  int t1;                   // Manda mensaje de datos de temperatura del motor derecho al Maestro
  int t2;                   // Manda mensaje de datos de temperatura del motor izquierdo al Maestro
  int ROVDepth;             // Manda mensaje de datos de lectura de profundidad de ROV (m)
  int ROVHDG;               // Manda mensaje de Dirección del ROV (grados)
  int h;                    // Manda mensaje de humedad al Maestro
  int h1;                   // Manda mensaje de humedad al Maestro del motor derecho
  int h2;                   // Manda mensaje de humedad al Maestro del motor izquierdo
  int AccX;                 // Manda mensaje de datos de inclinación del eje X al Maestro
  int AccY;                 // Manda mensaje de datos de inclinación del eje Y al Maestro
  int AccZ;                 // Manda mensaje de datos de de inclinación del eje Z al Maestro
  int Temp;                 // Manda mensaje de datos de temperatura del giroscopio al Maestro
  int GyroX;                // Manda mensaje de datos de aceleración en el eje X al Maestro
  int GyroY;                // Manda mensaje de datos de aceleración en el eje Y al Maestro
  int GyroZ;                // Manda mensaje de datos de aceleración en el eje Z al Maestro
  int E18D80NK;             // Manda mensaje de lectura del sensor infrarrojo E18-D80NK
  int pinLedColision;       // Manda mensaje de encender alarma de colisión
  int sensorDS18B20;        // Manda mensaje de lectura del sensor de temperatura DS18B20
  int pressure_bar;         // Manda mensaje de lectura del sensor de presión SKU237545 Interno en Bares
  int pressure_psi;         // Manda mensaje de lectura del sensor de presión SKU237545 Interno en PSI
  int pressure_bar1;        // Manda mensaje de lectura del sensor de presión SKU237545 Interno en Bares
  int pressure_psi1;        // Manda mensaje de lectura del sensor de presión SKU237545 Interno en PSI
};

RECEIVE_DATA_STRUCTURE rxdata; // Dar un nombre al grupo de datos recibidos
SEND_DATA_STRUCTURE txdata;    // Dar un nombre al grupo de datos enviados

void setup()
{

  // Se pone todo lo referente a la comunicación junta

  Wire.begin ();                           // Comienza la comunicación i2c

  Serial.begin(9600);                       // Comienza la Comunicación Serie para hablar con el ordenador a 9600 baudios
  Serial1.begin(9600);                     // Comienza la Comunicación Serie en el puerto 1, pines 18 y 19, para hablar con el Arduino Maestro
  Serial1.flush();                         // Depura la información del Puerto Serie
  ETin.begin(details(rxdata), & Serial1);  // Comienza la recepción de datos a través de Serial, en los pines 18 y 19
  ETout.begin(details(txdata), & Serial1); // Comienza el envío de datos a través de Serial, en los pines 18 y 19
  sensorDS18B20.begin();                   // Comienza el trabajo del sensor DS18B20

  // Se define el inicio del LED y de los Focos

  pinMode(RedLEDpin, OUTPUT);
  pinMode(HeadLts, OUTPUT);
  digitalWrite(HeadLts, LOW);  // Establezca los faros en Off
  digitalWrite(RedLEDpin, LOW);

  // Se inician los ESC y se define en que pin actúa cada uno
  ESCVL.arm();         // Inicia el ESCVL
  ESCVR.arm();         // Inicia el ESCVR
  ESCHL.arm();         // Inicia el ESCHL
  ESCHR.arm();         // Inicia el ESCHR

  // Esto hay que comprobarlo
  // Debido a problemas con el ESC que reconoce el máximo posición en la configuración predeterminada, las cifras después de
  // El número de pin son las señales de microsegundos para el mínimo y máximo que el ESC reconocerá, 600 y 2250 trabajo.

  ServoInmersion.attach(4); // Adjunte el servo de dirección al pin 4
  ServoInmersion.write(90); // Posiciona el servo inicialmente en la mitad (90°)

  // Se inician y se manda a imprimir la prueba de funcionamiento de los sensores DHT22
  dht.begin();  // Inicia el trabajo del sensor DHT22 del casco
  Serial.println (F(" \n Probando sensor DHT22 casco!"));
  dht1.begin(); // Inicia el trabajo del sensor DHT22 del motor derecho
  Serial.println (F(" \n Probando sensor DHT22 motor DR!"));
  dht2.begin(); // Inicia el trabajo del sensor DHT22 del motor izquierdo
  Serial.println (F(" \n Probando sensor DHT22 motor IZ!"));

  // Se inician los pines del sensor y de la alarma
  pinMode(pinSensorE18D80NK, INPUT_PULLUP); // Definir pin como sensor de entrada
  pinMode(pinLedColision, OUTPUT); // Definir pin como SALIDA para ACTION

  // Se inicia el pin del sensor de presión SKU237545 Interno
  pinMode (SensorSKU237545_I, INPUT);

  // Se inicia el pin del sensor de presión SKU237545 Externo
  pinMode (SensorSKU237545_E, INPUT);

  // Proceso para iniciar el giroscopio MPU6050
  Wire.begin();
  Wire.beginTransmission(MPU6050_addr);
  Wire.write(0x6B);
  Wire.write(0);
  Wire.endTransmission(true);

  delay (200);
}

void loop ()
{

  while (!ETin.receiveData())    // Recibe los datos al puerto serie para el ROV
  {
    Serial.print (F("\n Datos recibidos del Meastro.."));
    return;
  

  loop_ESC();             // Bloque de trabajo de los ESC de los motores
  loop_Luces();           // Bloque de trabajo de los focos
  loop_Voltaje();         // Bloque de trabajo para medir el voltaje de la batería
  loop_DHT22();           // Bloque de trabajo de los sensores de temperatura y humedad DHT22
  loop_MPU6050();         // Bloque de trabajo del Giroscopio
  loop_SensorE18D80NK();  // Bloque de trabajo del sensor de infrarrojos
  loop_DS18B20();         // Bloque de trabajo del sensor de temperatura DS18B20
  loop_SKU237545_I();     // Bloque de trabajo del sensor de presión interno
  loop_SKU237545_E();     // Bloque de trabajo del sensor de presión externo
  loop_ServoInmersion();  // Bloque de trabajo del servo

  PSB_PAD_UPstate = (rxdata.PSB_PAD_UPstate);         // Recibe lectura del botón Izquierda arriba al Esclavo
  PSB_PAD_DOWNstate = (rxdata.PSB_PAD_DOWNstate);     // Recibe lectura del botón Izquierda abajo al Esclavo
  PSB_PAD_LEFTstate = (rxdata.PSB_PAD_LEFTstate);     // Recibe lectura del botón Izquierda Izquierda al Esclavo
  PSB_PAD_RIGHTstate = (rxdata.PSB_PAD_RIGHTstate);   // Recibe lectura del botón Izquierda derecho al Esclavo
  PSB_BLUEstate = (rxdata.PSB_BLUEstate);             // Recibe lectura del botón Cruz azul al Esclavo
  PSB_GREENstate = (rxdata.PSB_GREENstate);           // Recibe lectura del botón Triangulo verde al Esclavo
  PSB_PINKstate = (rxdata.PSB_PINKstate);             // Recibe lectura del botón Cuadrado rosa al Esclavo
  PSB_REDstate = (rxdata.PSB_REDstate);               // Recibe lectura del botón Circulo rojo al Esclavo
  PSB_L1state = (rxdata.PSB_L1state);                 // Recibe lectura del botón Izquierda delante arriba al Esclavo
  PSB_L2state = (rxdata.PSB_L2state);                 // Recibe lectura del botón Izquierda delante abajo al Esclavo
  PSB_L3state = (rxdata.PSB_L3state);                 // Recibe lectura del botón Palo izquierdo abajo al Esclavo
  PSB_R1state = (rxdata.PSB_R1state);                 // Recibe lectura del botón Derecha delante arriba al Esclavo
  PSB_R2state = (rxdata.PSB_R2state);                 // Recibe lectura del botón Derecha delante abajo al Esclavo
  PSB_R3state = (rxdata.PSB_R3state);                 // Recibe lectura del botón Palo derecho abajo al Esclavo

  // No me deja generar un bloque de trabajo para los botones del mando
  // Por eso los pongo dentro del void loop genérico

  if (rxdata.PSB_PAD_UPstate)
    // Si presionamos el botón izquierda arriba
  {
    digitalWrite(yelLEDpin, HIGH);
    // Enciende el Led Amarillo
  }

  if (rxdata.PSB_PAD_DOWNstate)
    // Si presionamos el botón izquierda abajo
  {
    digitalWrite(yelLEDpin, HIGH);
    // Enciende el Led Amarillo
  }

  if (rxdata.PSB_PAD_RIGHTstate)
    // Si presionamos el botón izquierda derecha
  {
    digitalWrite(yelLEDpin, HIGH);
    // Enciende el Led Amarillo
  }

  if (rxdata.PSB_GREENstate)
    // Si presionamos triangulo verde
  {
    digitalWrite(yelLEDpin, HIGH);
    // Enciende el Led Amarillo
  }

  if (rxdata.PSB_REDstate)
    // Si presionamos el círculo rojo
  {
    digitalWrite(yelLEDpin, HIGH);
    // Enciende el Led Amarillo
  }

  if (rxdata.PSB_BLUEstate)
    // Si presionamos el cruz azul
  {
    digitalWrite(yelLEDpin, HIGH);
    // Enciende el Led Amarillo
  }

  if (rxdata.PSB_PINKstate)
    // Si presionamos el cuadrado rosa
  {
    digitalWrite(yelLEDpin, HIGH);
    // Enciende el Led Amarillo
  }

  if (rxdata.PSB_L1state)
    // Si presionamos el botón L1
  {
    digitalWrite(yelLEDpin, HIGH);
    // Enciende el Led Amarillo
  }

  if (rxdata.PSB_L2state)
    // Si presionamos el botón L2
  {
    digitalWrite(yelLEDpin, HIGH);
    // Enciende el Led Amarillo
  }

  if (rxdata.PSB_R1state)
    // Si presionamos el botón R1
  {
    // Enciende / apaga las luces
    digitalWrite(yelLEDpin, HIGH);
    // Enciende el Led Amarillo
  }

  if (rxdata.PSB_R2state)
    // Si presionamos el botón R2
  {
    // Enciende / apaga las luces
    digitalWrite(yelLEDpin, HIGH);
    // Enciende el Led Amarillo
  }

  if (rxdata.PSB_L3state)
    // Si presionamos el joystick izquierdo hacia abajo
  {
    digitalWrite(yelLEDpin, HIGH);
    // Enciende el Led Amarillo
  }

  if (rxdata.PSB_R3state)
    // Si presionamos el joystick derecho hacia abajo
  {
    digitalWrite(yelLEDpin, HIGH);
    // Enciende el LED Amarillo
  }

}
}

void loop_ESC() { // Bloque de trabajo de los ESC de los motores

  // Haremos algo correctamente con los datos devueltos en un
  ESCVL.speed(rxdata.upLraw);   // Establezca la señal ESCVL en la posición del acelerador definida.
  ESCVR.speed(rxdata.upRraw);   // Establezca la señal ESCVR en la posición del acelerador definida.
  ESCHL.speed(rxdata.HLraw);    // Establezca la señal ESCHL en la posición del acelerador definida.
  ESCHR.speed(rxdata.HRraw);    // Establezca la señal ESCHR en la posición del acelerador definida.

}

void loop_ServoInmersion() {         // Bloque de trabajo del Servo de Inmersión

  if (rxdata.PSB_R1state == LOW)
    // Aumenta el ángulo mientras se mantenga presionado
  {
    angulo++;
    if (angulo >= 180)
    {
      angulo = 180;
      // El ángulo no aumenta más allá de 180 grados
      Serial.print (F(" \n Subiendo ROV a superficie "));
    }
  }
  else if (rxdata.PSB_R2state == LOW)
    // Disminuye el ángulo mientras se mantenga presionado
  {
    angulo--;
    if (angulo <= 0)
    {
      angulo = 0;
      // El ángulo no disminuye mas allá de 0 grados
      Serial.print (F("\n Inmersion ROV a profundidad "));
    }
  }
  ServoInmersion.write(angulo);
  // Manda el ángulo al servo dependiendo del pulsador presionado
  //  delay(10);
}

void loop_Luces() { // Bloque de trabajo de los focos
  digitalWrite(HeadLts, rxdata.LEDHdlts);
  // Enciende los faros en función del retraso de los datos del mensaje
  if (rxdata.LEDHdlts > 0) {
    digitalWrite(HeadLts, LOW);
    Serial.print (F(" \n Focos apagados "));
  }
  else {
    (rxdata.LEDHdlts < 0);
    digitalWrite(HeadLts, HIGH);
    Serial.print (F(" \n Focos encendidos "));
  }
}

void loop_Voltaje() { // Bloque de trabajo de medición de voltaje de la batería

  volts = analogRead(Voltpin) / ResistFactor * RefVolts * 10; // Lee el voltaje
  // De la batería a través del divisor de voltaje. Factor de 10 utilizado
  // Para ayudar a lograr un número entero con una precisión de 0.1V.
  // Factor 10 utilizado para obtener precisión adicional del valor entero y luego se muestra con 1 decimal
  txdata.BattVolt = volts;  // Enviar de vuelta el voltaje de la batería a bordo.
  Serial.print (F(" \n Voltaje del ROV = "));
  Serial.print(volts);

}

void loop_DHT22() { // Bloque de trabajo de los sensores DHT22

  float h = dht.readHumidity();
  // Lectura de Humedad desde el sensor DHT22 del interior del ROV
  float t = dht.readTemperature();
  // Lectura de Temperatura desde el sensor DHT22 del interior del ROV
  float h1 = dht1.readHumidity();
  // Lectura de Humedad desde el sensor DHT22 del motor derecho
  float t1 = dht1.readTemperature();
  // Lectura de Temperatura desde el sensor DHT22 del motor derecho
  float h2 = dht2.readHumidity();
  // Lectura de Humedad desde el sensor DHT22 del motor izquierdo
  float t2 = dht2.readTemperature();
  // Lectura de Temperatura desde el sensor DHT22 del motor izquierdo
  int intervaloMedidas = 1000;
  // Hace que solo se lean los valores 1 vez por segundo
  unsigned long auxMillis = 0;
  // Indica el valor del intervalo de tiempo

  // Comprueba si hay fallo en todas las lecturas y sale rápido y prueba otra vez
  if (isnan(h) || isnan(t)) {
    Serial.print (F(" \n Fallo de lectura desde el sensor DHT del Casco!"));
    return;
  }
  else if (isnan(h1) || isnan(t1)) {
    Serial.print (F(" \n Fallo de lectura desde el sensor DHT del motor DR!"));
    return;
  }
  else if (isnan(h2) || isnan(t2)) {
    Serial.print (F(" \n Fallo de lectura desde el sensor DHT del motor IZ!"));
    return;
  }
  else if (( millis() - auxMillis) > intervaloMedidas) {
    txdata.t = t;   // Envía al Maestro la temperatura leída en el casco
    txdata.h = h;   // Envía al Maestro la humedad leída en el casco
    txdata.t1 = t1; // Envía al Maestro la temperatura leída en el motor derecho
    txdata.h1 = h1; // Envía al Maestro la humedad leída en el motor derecho
    txdata.t2 = t2; // Envía al Maestro la temperatura leída en el motor izquierdo
    txdata.h2 = h2; // Envía al Maestro la humedad leída en el motor izquierdo
    auxMillis = millis();
  }
  else if (t > 40 || t1 > 40 || t2 > 40)
  {
    // Si la temperatura de cualquiera de los sensores DHT22 es demasiado alta (más de 40 grados C)
    // Enciende el LED de advertencia
    digitalWrite(TwarnLEDpin, HIGH);
    // Enciende la bomba de refrigeración
    digitalWrite(Refrigeracion, HIGH);
    // Escribe el texto
    Serial.print (F(" \n TEMPERATURA ELEVADA !"));
  }
  Serial.print (F(" \n Temperatura en el casco = "));
  Serial.print (t);
  Serial.print (F(" *C "));
  Serial.print (F(" \n Temperatura en el motor DR = "));
  Serial.print (t1);
  Serial.print (F(" *C1 "));
  Serial.print (F(" \n Temperatura en el motor IZ = "));
  Serial.print (t2);
  Serial.print (F(" *C2 "));
  Serial.print (F(" \n Humedad en el Casco = "));
  Serial.print (h);
  Serial.print (F(" %\t"));
  Serial.print (F(" \n Humedad en el motor DR = "));
  Serial.print (h1);
  Serial.print (F(" %\t"));
  Serial.print (F(" \n Humedad en el motor IZ = "));
  Serial.print (h2);
  Serial.print (F(" %\t"));

}

void loop_MPU6050() {  // Bloque de trabajo del giroscopio

  Wire.beginTransmission(MPU6050_addr);
  Wire.write(0x3B);
  Wire.endTransmission(false);
  Wire.requestFrom(MPU6050_addr, 14, true);
  AccX = Wire.read() << 8 | Wire.read();
  AccY = Wire.read() << 8 | Wire.read();
  AccZ = Wire.read() << 8 | Wire.read();
  Temp = Wire.read() << 8 | Wire.read();
  GyroX = Wire.read() << 8 | Wire.read();
  GyroY = Wire.read() << 8 | Wire.read();
  GyroZ = Wire.read() << 8 | Wire.read();

  txdata.AccX = AccX;
  txdata.AccY = AccY;
  txdata.AccZ = AccZ;
  txdata.Temp = Temp;
  txdata.GyroX = GyroX;
  txdata.GyroY = GyroY;
  txdata.GyroZ = GyroZ;

  Serial.print (F(" \n Inclinación del eje X del ROV = "));
  Serial.print (AccX);
  Serial.print (F(" \n Inclinación del eje Y del ROV = "));
  Serial.print (AccY);
  Serial.print (F(" \n Inclinación del eje Z del ROV = "));
  Serial.print (AccZ);
  Serial.print (F(" \n Temperatura del Giro MPU6050 = "));
  Serial.print (Temp / 340.00 + 36.53);
  Serial.print (F(" \n Aceleración del Giro MPU6050 = "));
  Serial.print (GyroX);
  Serial.print (F(" \n Aceleración del Giro MPU6050 = "));
  Serial.print (GyroY);
  Serial.print (F(" \n Aceleración del Giro MPU6050 = "));
  Serial.print(GyroZ);

  // Serial.print(" \n Dirección del ROV = ");
  //  Serial.print(rxdata.ROVHDG);  // muestra la dirección del ROV en una brújula

  Wire.endTransmission(MPU6050_addr); //

}

void loop_SensorE18D80NK() { // Bloque de trabajo del sensor infrarrojo

  int E18D80NK = digitalRead(pinSensorE18D80NK); // leer el Sensor

  if (E18D80NK > 0) {
    Serial.println (F(" \n Todo despejado"));
    digitalWrite(pinLedColision, LOW); // encender el LED de peligro
  }
  else {
    Serial.println (F(" \n Peligro Objeto detectado"));
    digitalWrite(pinLedColision, HIGH); // Apagar el LED de peligro
  }
  txdata.E18D80NK = E18D80NK;
}

void loop_DS18B20() {  // Bloque de trabajo del sensor de temperatura DS18B20

  sensorDS18B20.requestTemperatures();
  Serial.print (F("\n Temperatura sensor DS18B20 = "));
  Serial.print (sensorDS18B20.getTempCByIndex(0));
  Serial.print (F(" ºC"));
  txdata.sensorDS18B20 = sensorDS18B20.getTempCByIndex(0);
}

void loop_SKU237545_I() { // Bloque de trabajo del sensor de presión interno

  SensorSKU237545_I = analogRead(32);
  float voltage = (SensorSKU237545_I * 5.0) / 1024.0;
  float pressure_pascal = (3.0 * ((float)voltage - 0.475)) * 1000000.0;  //calibrar aquí
  float pressure_bar = pressure_pascal / 10e5;
  float pressure_psi = pressure_bar * 14.5038;
  Serial.print (F(" \n Valor del Sensor de Presión Interno =  "));
  Serial.print (SensorSKU237545_I);
  Serial.print (F(" \n Presión en Bar = "));
  Serial.print (pressure_bar);
  Serial.print (F("    bars"));
  Serial.print (F(" \n Presión en PSI = "));
  Serial.print (pressure_psi);
  Serial.print (F("   psi"));
  txdata.pressure_bar = pressure_bar;
  txdata.pressure_psi = pressure_psi;
}

void loop_SKU237545_E() {  // bloque de trabajo del sensor de presión externo

  SensorSKU237545_E = analogRead(32);
  float voltage1 = (SensorSKU237545_E * 5.0) / 1024.0;
  float pressure_pascal1 = (3.0 * ((float)voltage1 - 0.475)) * 1000000.0;  //calibrar aquí
  float pressure_bar1 = pressure_pascal1 / 10e5;
  float pressure_psi1 = pressure_bar1 * 14.5038;
  Serial.print (F(" \n Valor del Sensor de Presión Externo = "));
  Serial.print (SensorSKU237545_E);
  Serial.print (F(" Presión en Bar = "));
  Serial.print (pressure_bar1);
  Serial.print (F("    bars"));
  Serial.print (F(" \n Presión en PSI = "));
  Serial.print (pressure_psi1);
  Serial.print (F("   psi"));
  Serial.print (F(" \n Profundidad = "));
  txdata.pressure_bar1 = pressure_bar1;
  txdata.pressure_psi1 = pressure_psi1;

  // Serial.print(rxdata.ROVDepth);
  // Muestra en el Display la profundidad del ROV en metros

  
  ETout.sendData ();     // Envía los datos al puerto serie para el ROV Arduino

}
asesorplaza1
Colaborador
Colaborador
Mensajes: 209
Registrado: Jue Ene 24, 2019 6:51 am
Ubicación: Cuenca

Re: Un ROV de agua dulce, con mando de PS2

Mensaje por asesorplaza1 »

Buenas tardes.

He realizado los cambios sugeridos por Tsanahon, y he tenido que hacer algo mal, porque esto sigue sin funcionar.

He adjuntado los dos códigos sin el texto del encabezamiento, para que me quepa en la publicación como código, si no, no me cabe, y ahora adjunto los códigos comprimidos.
Adjuntos
50_16_05_2020.rar
(16.34 KiB) Descargado 90 veces
asesorplaza1
Colaborador
Colaborador
Mensajes: 209
Registrado: Jue Ene 24, 2019 6:51 am
Ubicación: Cuenca

Re: Un ROV de agua dulce, con mando de PS2

Mensaje por asesorplaza1 »

Buenas noches.

Como no dejo de darle vueltas a porque no funciona el programa, me he dado cuenta de que había unas ordenes que estorbaban mas que otra cosa, y las he corregido, por lo tanto los códigos buenos, aunque no funcionan, son estos que voy a poner ahora.

Un saludo.
asesorplaza1
Colaborador
Colaborador
Mensajes: 209
Registrado: Jue Ene 24, 2019 6:51 am
Ubicación: Cuenca

Re: Un ROV de agua dulce, con mando de PS2

Mensaje por asesorplaza1 »

Código Maestro

Código: Seleccionar todo

#include <PS2X_lib.h> // Librería PS2 de Bill Porter
#include <EasyTransfer.h> // Librería Easy Transfer de Bill Porter

PS2X ps2x;         // Crea la clase del controlador PS2
int error = 0;     // Crea la clase de error del mando
byte type = 0;     // Crea el tipo de error del mando
byte vibrate = 0;  // Crea la vibracion del mando

EasyTransfer ETin, ETout;  //Cree los objetos de EasyTransfer para la comunicación bidireccional

const int grnLEDpin = 30;       // LED verde    esta encendido en pin Digital 4
const int redLEDpin = 31;       // LED rojo     esta encendido en pin Digital 3
const int yelLEDpin = 32;       // LED amarillo esta encendido en pin Digital 2
const int VwarnLEDpin = 33;     // LED de advertencia de voltaje esta encendido en el Pin digital D5
const int TwarnLEDpin = 34;     // LED de advertencia de temperatura esta encendido en el pin D6
const int pinLedColision = 35;  // LED de advertencia de peligro colisión en el pin 27
const int LowBatVolts10 = 96;   // esto es para mantener el valor de advertencia de voltaje de bateria bajo en el umbral de x10.

int ForwardVal = 0;             // valor leído en palo PS2 derecho arriba/abajo
int YawLeftVal = 0;             // valor leído en palo PS2 derecho derecha/izquierda
int UpVal = 0;                  // valor leído en palo PS2 izquierdo arriba/abajo
int RollLeftVal = 0;            // valor leído en palo PS2 izquierdo derecha/izquierda

boolean PSB_PAD_UPstate = false;     // Genera variable para guardar y mandar los datos del botón Izquierda arriba al Esclavo
boolean PSB_PAD_DOWNstate = false;   // Genera variable para guardar y mandar los datos del botón Izquierda abajo al Esclavo
boolean PSB_PAD_LEFTstate = false;   // Genera variable para guardar y mandar los datos del botón Izquierda izquierdo al Esclavo
boolean PSB_PAD_RIGHTstate = false;  // Genera variable para guardar y mandar los datos del botón Izquierda derecho al Esclavo
boolean PSB_BLUEstate = false;       // Genera variable para guardar y mandar los datos del botón Cruz azul al Esclavo
boolean PSB_GREENstate = false;      // Genera variable para guardar y mandar los datos del botón Triangulo verde al Esclavo
boolean PSB_PINKstate = false;       // Genera variable para guardar y mandar los datos del botón Cuadrado rosa al Esclavo
boolean PSB_REDstate = false;        // Genera variable para guardar y mandar los datos del botón Circulo rojo al Esclavo
boolean PSB_L1state = false;         // Genera variable para guardar y mandar los datos del botón Izquierda delante arriba al Esclavo
boolean PSB_L2state = false;         // Genera variable para guardar y mandar los datos del botón Izquierda delante abajo al Esclavo
boolean PSB_L3state = false;         // Genera variable para guardar y mandar los datos del botón Palo izquierdo abajo al Esclavo
boolean PSB_R1state = false;         // Genera variable para guardar y mandar los datos del botón Derecha delante arriba al Esclavo
boolean PSB_R2state = false;         // Genera variable para guardar y mandar los datos del botón Derecha delante abajo al Esclavo
boolean PSB_R3state = false;         // Genera variable para guardar y mandar los datos del botón Palo derecho abajo al Esclavo

float ROVTMP = 0;                                  // Variable para recibir los datos de la temperatura interior del ROV
float ROVTMP1 = 0;                                 // Variable para recibir los datos de la temperatura motor derecho del ROV
float ROVTMP2 = 0;                                 // Variable para recibir los datos de la temperatura motor izquierdo del ROV
float ROVDHThumid;                                 // Variable para recibir los datos de la humedad interior del ROV
float ROVDHThumid1;                                // Variable para recibir los datos de la humedad del motor derecho del ROV
float ROVDHThumid2;                                // Variable para recibir los datos de la humedad del motor izquierda del ROV
float AccX, AccY, AccZ, Temp, GyroX, GyroY, GyroZ; // Variable para recibir los datos del Giroscopio del ROV
float E18D80NK;                                    // Variable para recibir los datos del sensor E18D80NK del ROV
float sensorDS18B20;                               // Variable para recibir los datos del sensor DS18B20 del ROV
float pressure_bar;                                // Variable para recibir los datos del sensor de presión interior SKU237545 en Bares del ROV
float pressure_psi;                                // Variable para recibir los datos del sensor de presión interior SKU237545 en PSI del ROV
float pressure_bar1;                               // Variable para recibir los datos del sensor de presión exterior SKU237545 en Bares del ROV
float pressure_psi1;                               // Variable para recibir los datos del sensor de presión interior SKU237545 en PSI del ROV
float ROVDepth;                                    // Variable para recibir los datos de la profundidad a la que se encuentra el ROV
float ROVHDG;                                      // Variable para recibir los datos de la dirección del ROV en grados

struct RECEIVE_DATA_STRUCTURE  // estructura de mensaje de datos recibidos de los sensores
{
  int BattVolt;             // Recibe mensaje de voltaje de batería
  int t;                    // Recibe mensaje de temperatura interior del ROV
  int t1;                   // Recibe mensaje de temperatura del motor derecho
  int t2;                   // Recibe mensaje de temperatura del motor izquierdo
  int ROVDepth;             // Recibe mensaje de lectura de profundidad de ROV (m)
  int ROVHDG;               // Recibe mensaje de Dirección del ROV (grados)
  int h;                    // Recibe mensaje de humedad del interior del ROV
  int h1;                   // Recibe mensaje de humedad del motor derecho
  int h2;                   // Recibe mensaje de humedad del motor izquierdo
  int AccX;                 // Recibe mensaje de datos de inclinación del eje X
  int AccY;                 // Recibe mensaje de datos de inclinación del eje Y
  int AccZ;                 // Recibe mensaje de datos de inclinación del eje Z
  int Temp;                 // Recibe mensaje de datos de temperatura del giroscopio
  int GyroX;                // Recibe mensaje de datos de aceleración en el eje X
  int GyroY;                // Recibe mensaje de datos de aceleración en el eje Y
  int GyroZ;                // Recibe mensaje de datos de aceleración en el eje Z
  int E18D80NK;             // Recibe mensaje de lectura del sensor infrarrojo E18-D80NK
  int pinLedColision;       // Recibe mensaje de encender alarma de colisión
  int sensorDS18B20;        // Recibe mensaje de lectura del sensor de temperatura DS18B20
  int pressure_bar;         // Recibe mensaje de lectura del sensor de presión SKU237545 en Bares
  int pressure_psi;         // Recibe mensaje de lectura del sensor de presión SKU237545 en PSI
  int pressure_bar1;        // Recibe mensaje de lectura del sensor de presión SKU237545 Interno en Bares
  int pressure_psi1;        // Recibe mensaje de lectura del sensor de presión SKU237545 Interno en PSI
};

struct SEND_DATA_STRUCTURE  // estructura de mensaje de datos enviados
{
  int upLraw = 0;  //Variables para transportar los datos reales sin procesar de los ESCs
  int upRraw = 0;
  int HLraw = 0;
  int HRraw = 0;
  volatile boolean PSB_PAD_UPstate;     // Manda lectura del botón Izquierda arriba al Esclavo
  volatile boolean PSB_PAD_DOWNstate;   // Manda lectura del botón Izquierda abajo al Esclavo
  volatile boolean PSB_PAD_RIGHTstate;  // Manda lectura del botón Izquierda derecho al Esclavo
  volatile boolean PSB_PAD_LEFTstate;   // Manda lectura del botón Izquierda Izquierda al Esclavo
  volatile boolean PSB_BLUEstate;       // Manda lectura del botón Cruz azul al Esclavo
  volatile boolean PSB_GREENstate;      // Manda lectura del botón Triangulo verde al Esclavo
  volatile boolean PSB_PINKstate;       // Manda lectura del botón Cuadrado rosa al Esclavo
  volatile boolean PSB_REDstate;        // Manda lectura del botón Circulo rojo al Esclavo
  volatile boolean PSB_L1state;         // Manda lectura del botón Izquierda delante arriba al Esclavo
  volatile boolean PSB_L2state;         // Manda lectura del botón Izquierda delante abajo al Esclavo
  volatile boolean PSB_L3state;         // Manda lectura del botón Palo izquierdo abajo al Esclavo
  volatile boolean PSB_R1state;         // Manda lectura del botón Derecha delante arriba al Esclavo
  volatile boolean PSB_R2state;         // Manda lectura del botón Derecha delante abajo al Esclavo
  volatile boolean PSB_R3state;         // Manda lectura del botón Palo derecho abajo al Esclavo
  volatile boolean LEDHdlts;            // Manda que hacer con los Focos, encendidos/apagados
};

//dar un nombre al grupo de datos
RECEIVE_DATA_STRUCTURE rxdata;
SEND_DATA_STRUCTURE txdata;

unsigned long a = millis();  // Se define y se inicia una variable llamada millis

void setup()
{

  Serial.begin(9600);      // Comienza la Comunicación en Serie para hablar con el ordenador a 9600 Baudios
  Serial1.begin(9600);    // Comienza la comunicación Serie en el puerto 1, pines 18 y 19, para hablar con el Arduino Esclavo
  Serial1.flush();         // Depura la información del Puerto Serie
  ETin.begin(details(rxdata), &Serial1);    // Comienza la recepción de datos a través de Serial, en los pines 18 y 19
  ETout.begin(details(txdata), &Serial1);   // Comienza el envío de datos a través de Serial, en los pines 18 y 19

  pinMode(grnLEDpin, OUTPUT);  //se establece grnLEDpin como salida
  pinMode(redLEDpin, OUTPUT);  //se establece redLEDpin como salida
  pinMode(yelLEDpin, OUTPUT);  //se establece yelLEDpin como salida
  pinMode(VwarnLEDpin, OUTPUT);  //se establece el pin de advertencia de batería baja como salida
  pinMode(TwarnLEDpin, OUTPUT);  //se establece el pin de sobre temperatura como salida

  // Pines y ajustes de configuración: GamePad(clock, command, attention, data, Pressures?, Rumble?)
  error = ps2x.config_gamepad(22, 23, 24, 25, false, false);

  if (error == 0)
  {
    Serial.println (F("\n Controlador encontrado y configurado con éxito"));
  }

  else if (error == 1)
    Serial.println (F(" \n No se encontró el controlador, verifique el cableado, consulte readme.txt para habilitar la depuración. Visite www.billporter.info para obtener sugerencias para la solución de problemas"));

  else if (error == 2)
    Serial.println (F(" \n El controlador se encontró, pero no admite comandos. Consulte readme.txt para habilitar la depuración. Visite www.billporter.info para obtener sugerencias para la solución de problemas"));

  else if (error == 3)
    Serial.println (F(" \n El controlador se niega a ingresar en el modo de presiones, puede que no lo admita"));

  // Serial.print(ps2x.Analog(1), HEX);
  type = ps2x.readType();
}

void loop()
{

  if (millis() > a + 100) {


    if (error == 0)
    {
      // Controlador DualShock
      ps2x.read_gamepad();

      //lecturas analógicas del palo
      //traduce las lecturas del palo al las instrucciones del ESC
      //las lecturas de los palos del controlador PS2 son de 0 a 255
      //con el neutro en 128. Las posiciones cero son
      //a la izquierda para movimientos del eje X y arriba para los movimientos del eje Y

      ForwardVal = ps2x.Analog(PSS_RY);
      YawLeftVal = ps2x.Analog(PSS_RX);
      UpVal = ps2x.Analog(PSS_LY);
      RollLeftVal = ps2x.Analog(PSS_LX);

      // Lectura de todos los botones del mando
      // Esto será verdad hasta que algún botón cambie de estado, (activado / desactivado)
      if (ps2x.NewButtonState())
      {
        if (ps2x.ButtonPressed(PSB_PAD_UP))                // Lee el valor del botón Izquierda arriba al Esclavo
        {
          PSB_PAD_UPstate = (!PSB_PAD_UPstate);            // Guarda el dato del botón en su variable
          digitalWrite(yelLEDpin, PSB_PAD_UPstate);        // Enciende el LED Amarillo
        }
        txdata.PSB_PAD_UPstate = (PSB_PAD_UPstate);        // Manda el estado del botón al Esclavo

        if (ps2x.ButtonPressed(PSB_PAD_DOWN))              // Lee el valor del botón Izquierda abajo al Esclavo
        {
          PSB_PAD_DOWNstate = (!PSB_PAD_DOWNstate);            // Guarda el dato del botón en su variable
          digitalWrite(yelLEDpin, PSB_PAD_DOWNstate);      // Enciende el LED Amarillo
        }
        txdata.PSB_PAD_DOWNstate = (PSB_PAD_DOWNstate);    // Manda el estado del botón al Esclavo

        if (ps2x.ButtonPressed(PSB_PAD_RIGHT))             // Lee el valor del botón Izquierda derecho al Esclavo
        {
          PSB_PAD_RIGHTstate = (!PSB_PAD_RIGHTstate);      // Guarda el dato del botón en su variable
          digitalWrite(yelLEDpin, PSB_PAD_RIGHT);          // Enciende el LED Amarillo
        }
        txdata.PSB_PAD_RIGHTstate = (PSB_PAD_RIGHTstate);  // Manda el estado del botón al Esclavo

        if (ps2x.Button(PSB_PAD_LEFT))                     // Lee el valor del botón Izquierda Izquierda al Esclavo
        {
          PSB_PAD_LEFTstate = (!PSB_PAD_LEFTstate);        // Lectura del estado del botón
          txdata.LEDHdlts = PSB_PAD_LEFTstate;             // Guarda que hacer con el estado de los focos, encendido / apagado
          digitalWrite(yelLEDpin, PSB_PAD_LEFTstate);      // Enciende el Led Amarillo
          Serial.print (F("\n Focos apagados"));           // Imprime la frase "Focos apagados"
        }
        else if (!txdata.LEDHdlts)
        {
          digitalWrite(yelLEDpin, LOW);                    // Apaga el led amarillo
          Serial.print (F("\n Focos encendidos"));         // Imprime la frase " Focos encendidos"
        }

        txdata.PSB_PAD_LEFTstate = (PSB_PAD_LEFTstate);    // Manda el estado del botón al Esclavo

        if (ps2x.ButtonPressed(PSB_BLUE))                  // Lee el valor del botón Cruz azul al Esclavo
        {
          PSB_BLUEstate = (!PSB_BLUEstate);                // Guarda el dato del botón en su variable
          digitalWrite(yelLEDpin, PSB_BLUEstate);          // Enciende el Led Amarillo
        }
        txdata.PSB_BLUEstate = (PSB_BLUEstate);            // Manda el estado del botón al Esclavo

        if (ps2x.ButtonPressed(PSB_GREEN))                 // Lee el valor del botón Triangulo verde al Esclavo
        {
          PSB_GREENstate = (!PSB_GREENstate);              // Guarda el dato del botón en su variable
          digitalWrite(yelLEDpin, PSB_GREENstate);         // Enciende el LED Amarillo
        }
        txdata.PSB_GREENstate = (PSB_GREENstate);          // Manda el estado del botón al Esclavo

        if (ps2x.ButtonPressed(PSB_PINK))                  // Lee el valor del botón Cuadrado rosa al Esclavo
        {
          PSB_PINKstate = (!PSB_PINKstate);                // Guarda el dato del botón en su variable
          digitalWrite(yelLEDpin, PSB_PINKstate);          // Enciende el LED Amarillo
        }
        txdata.PSB_PINKstate = (PSB_PINKstate);            // Manda el estado del botón al Esclavo

        if (ps2x.ButtonPressed(PSB_RED))                   // Lee el valor del botón Circulo rojo al Esclavo
        {
          PSB_REDstate = (!PSB_REDstate);                  // Guarda el dato del botón en su variable
          digitalWrite(yelLEDpin, PSB_REDstate);           // Enciende el LED Amarillo
        }
        txdata.PSB_REDstate = (PSB_REDstate);              // Manda el estado del botón al Esclavo

        if (ps2x.ButtonPressed(PSB_L3))                    // Lee el valor del botón Palo izquierdo abajo al Esclavo
        {
          PSB_L3state = (!PSB_L3state);                    // Guarda el dato del botón en su variable
          digitalWrite(yelLEDpin, PSB_L3state);            // Enciende el Led Amarillo
        }
        txdata.PSB_L3state = (PSB_L3state);                // Manda el estado del botón al Esclavo

        if (ps2x.ButtonPressed(PSB_R1))                    // Lee el valor del botón Derecha delante arriba al Esclavo
        {
          PSB_R1state = (!PSB_R1state);                    // Guarda el dato del botón en su variable
          digitalWrite(yelLEDpin, PSB_R1state);            // Enciende el Led Amarillo
        }
        txdata.PSB_R1state = (PSB_R1state);                // Manda el estado del botón al Esclavo

        if (ps2x.ButtonPressed(PSB_R2))                    // Lee el valor del botón Derecha delante abajo al Esclavo
        {
          PSB_R2state = (!PSB_R2state);                    // Guarda el dato del botón en su variable
          digitalWrite(yelLEDpin, PSB_R2state);            // Enciende el Led Amarillo
        }
        txdata.PSB_R2state = (PSB_R2state);                // Manda el estado del botón al Esclavo

        if (ps2x.Button(PSB_R3))                           // Lee el valor del botón Palo derecho abajo al Esclavo
        {
          PSB_R3state = (!PSB_R3state);                    // Guarda el dato del botón en su variable
          digitalWrite(yelLEDpin, PSB_R3state);            // Enciende el Led Amarillo
        }
        txdata.PSB_R3state = (PSB_R3state);                // Manda el estado del botón al Esclavo

        if (ps2x.ButtonPressed(PSB_L1))                    // Lee el valor del botón Izquierda delante arriba al Esclavo
        {
          PSB_L1state = (!PSB_L1state);                    // Guarda el dato del botón en su variable
          digitalWrite(yelLEDpin, PSB_L1state);            // Enciende el Led Amarillo
        }
        txdata.PSB_L1state = (PSB_L1state);                // Manda el estado del botón al Esclavo

        if (ps2x.ButtonPressed(PSB_L2))                    // Lee el valor del botón Izquierda delante abajo al Esclavo
        {
          PSB_L2state = (!PSB_L2state);                    // Guarda el dato del botón en su variable
          digitalWrite(yelLEDpin, PSB_L2state);            // Enciende el Led Amarillo
        }
        txdata.PSB_L2state = (PSB_L2state);                // Manda el estado del botón al Esclavo
      }

      //variables para transportar los datos en bruto reales para los ESCs y servos
      txdata.upLraw = (128 - UpVal) - (128 - RollLeftVal) / 2; //esto será hasta un valor de 192
      txdata.upRraw = (128 - UpVal) + (128 - RollLeftVal) / 2; //esto será hasta un valor de 192
      txdata.HLraw = -(128 - ForwardVal) + (128 - YawLeftVal); //esto será hasta un valor de 256
      txdata.HRraw = -(128 - ForwardVal) - (128 - YawLeftVal); //esto será hasta un valor de 256
      //escala los valores para que sean adecuados para los ESCs y para los Servos
      //estos valores podrán escribirse directamente en los  ESCs y en los Servos
      txdata.upLraw = map(txdata.upLraw, -193, 193, 0, 179);
      txdata.upRraw = map(txdata.upRraw, -193, 198, 0, 179);
      txdata.HLraw = map(txdata.HLraw, -256, 256, 0, 179);
      txdata.HRraw = map(txdata.HRraw, -256, 256, 0, 179);
    }

    // Enviar el mensaje al puerto serie para el Arduino del ROV
    ETout.sendData();

    for (int i = 0; i < 5; i++) {

      a = millis();
    }

    if (ETin.receiveData())    // Recibe el mensaje al puerto serie para el Arduino del ROV
    {
      if (rxdata.BattVolt < LowBatVolts10)
        // el factor de 10 se incluye para coincidir con el factor 10 utilizado en el valor informado que es un int multiplicado
        // Por 10 para dar una precisión de 0.1 al valor. Tiene sentido
      {
        digitalWrite(VwarnLEDpin, HIGH);
        //si el voltaje de la batería es demasiado bajo, enciende el LED de advertencia
      }
      else
      {
        digitalWrite(VwarnLEDpin, LOW);
        //de lo contrario, si el voltaje está por encima del umbral de bajo voltaje definido
        //deje el LED apagado
      }

      ROVTMP = (rxdata.t);    // Recibe los datos del Esclavo
      ROVTMP1 = (rxdata.t1);  // Recibe los datos del Esclavo
      ROVTMP2 = (rxdata.t2);  // Recibe los datos del Esclavo
      //convierte el valor de datos 0-1024 en temperatura

      if (ROVTMP > 50 || ROVTMP1 > 50 || ROVTMP2 > 50)
      {
        // Si la temperatura de cualquiera de los sensores DHT22 es demasiado alta (más de 50 grados C)
        // enciende el LED de advertencia
        digitalWrite(TwarnLEDpin, HIGH);
        Serial.print (F(" \n TEMPERATURA ELEVADA !"));
      }
      else
      {
        digitalWrite(TwarnLEDpin, LOW);
        Serial.print (F(" \n Temperatura Normal"));
        // De lo contrario, si la temperatura interior está en un nivel aceptable
        // Deje el LED apagado y deje el relé de la bomba de refrigeración apagado
      }

      ROVDHThumid = (rxdata.h);    // Recibe los datos del Esclavo
      ROVDHThumid1 = (rxdata.h1);  // Recibe los datos del Esclavo
      ROVDHThumid2 = (rxdata.h2);  // Recibe los datos del Esclavo

      if (rxdata.E18D80NK > 0)    // Si la entrada del E18D80NK es baja, no hay ningún objeto
      {
        digitalWrite(pinLedColision, LOW);    // Apague el LED si no se detecta objeto
        Serial.print (F(" \n Todo Despejado  !"));   // manda imprimir al Monitor Serie la frase
      }
      else                                    // por el contrario, si la entrada del E18D80NK es alta
      {
        digitalWrite(pinLedColision, HIGH);   // encienda el LED de Peligro Colisión
        Serial.print (F(" \n PELIGRO Obstaculo detectado  !")); // manda imprimir la frase
      }

      ROVDepth = (rxdata.ROVDepth);             // Recibe lectura de profundidad de ROV (m)
      ROVHDG = (rxdata.ROVHDG);                 // Recibe lectura de Dirección del ROV (grados)
      AccX = (rxdata.AccX);                     // Recibe lectura de datos de inclinación del eje X
      AccY = (rxdata.AccY);                     // Recibe lectura de datos de inclinación del eje Y
      AccZ = (rxdata.AccZ);                     // Recibe lectura de datos de inclinación del eje Z
      Temp = (rxdata.Temp);                     // Recibe lectura de datos de temperatura del giroscopio
      GyroX = (rxdata.GyroX);                   // Recibe lectura de datos de aceleración en el eje X
      GyroY = (rxdata.GyroY);                   // Recibe lectura de datos de aceleración en el eje Y
      GyroZ = (rxdata.GyroZ);                   // Recibe lectura de datos de aceleración en el eje Z
      //  pinLedColision = (rxdata.pinLedColision); // Recibe lectura de encender alarma de colisión
      sensorDS18B20 = (rxdata.sensorDS18B20);   // Recibe lectura de lectura del sensor de temperatura DS18B20
      pressure_bar = (rxdata.pressure_bar);     // Recibe lectura de lectura del sensor de presión SKU237545 en Bares
      pressure_psi = (rxdata.pressure_psi);     // Recibe lectura de lectura del sensor de presión SKU237545 en PSI
      pressure_bar1 = (rxdata.pressure_bar1);   // Recibe lectura de lectura del sensor de presión SKU237545 Interno en Bares
      pressure_psi1 = (rxdata.pressure_psi1);   // Recibe lectura de lectura del sensor de presión SKU237545 Interno en PSI
      E18D80NK = (rxdata.E18D80NK);             // Recibe estado del sensor de infrarrojos


      // #if DEBUG1 { // CUIDADO CON ESTO, des comentar y cambiar 1 si imprime en Monitor Serie, 0 cero no imprime


      // A partir de aquí repito las ordenes de lcd, cambiándolas por Serial

      Serial.print (F("\n Voltaje del ROV = "));
      Serial.print (float(rxdata.BattVolt) / 10, 1);
      //factor 10 utilizado para obtener precisión adicional del valor entero y luego se muestra con 1 decimal
      Serial.print (F(" \n Temperatura del casco = "));
      Serial.print (ROVTMP);
      Serial.print (F(" *C "));
      Serial.print (F(" \n Temperatura motor DR = "));
      Serial.print (ROVTMP1);
      Serial.print (F(" *C1 "));
      Serial.print (F(" \n Temperatura motor IZ = "));
      Serial.print (ROVTMP2);
      Serial.print (F(" *C2 "));
      Serial.print (F(" \n Humedad en el interior del Casco = "));
      Serial.print (ROVDHThumid);
      Serial.print (F(" %\t"));
      Serial.print (F(" \n Humedad en el motor DR = "));
      Serial.print (ROVDHThumid1);
      Serial.print (F(" %\t"));
      Serial.print (F(" \n Humedad en el motor IZ = "));
      Serial.print (ROVDHThumid2);
      Serial.print (F(" %\t"));
      Serial.print (F(" \n Inclinación del eje X del ROV = "));
      Serial.print (AccX);
      Serial.print (F(" \n Inclinación del eje Y del ROV = "));
      Serial.print (AccY);
      Serial.print (F(" \n Inclinación del eje Z del ROV = "));
      Serial.print (AccZ);
      Serial.print (F(" \n Temperatura del Giro MPU6050 = "));
      Serial.print (Temp / 340.00 + 36.53);
      Serial.print (F(" \n Aceleración en el eje X del Giro MPU6050 = "));
      Serial.print (GyroX);
      Serial.print (F(" \n Aceleración en el eje Y del Giro MPU6050 = "));
      Serial.print (GyroY);
      Serial.print (F(" \n Aceleración en el eje Z del Giro MPU6050 = "));
      Serial.print (GyroZ);
      Serial.print (F(" \n Profundidad = "));
      Serial.print (ROVDepth);      // muestra en el Display la profundidad del ROV en metros
      Serial.print (F(" \n Direccion del ROV = "));
      Serial.print (ROVHDG);  // muestra la dirección del ROV en una brújula
      Serial.print (F(" \n Temperatura sensor DS18B20 = "));
      Serial.print (sensorDS18B20);
      Serial.print (F(" ºC"));
      Serial.print (F(" \n Valor del Sensor de Presión Interno =  "));
      Serial.print (F("   Presión en Bar = "));
      Serial.print (pressure_bar);
      Serial.print (F("    bars"));
      Serial.print (F("  || Presión en PSI = "));
      Serial.print (pressure_psi);
      Serial.print (F("    psi"));
      Serial.print (F(" \n Valor del Sensor de Presión Externo = "));
      Serial.print (F("   Presión en Bar = "));
      Serial.print (pressure_bar1);
      Serial.print (F("    bars"));
      Serial.print (F("  || Presión en PSI = "));
      Serial.print (pressure_psi1);
      Serial.print (F("    psi"));
      Serial.print (F("\n"));
    }
    // } #endif  // des comentar cuando NO quiera imprimir los Serial.print


  }
}
asesorplaza1
Colaborador
Colaborador
Mensajes: 209
Registrado: Jue Ene 24, 2019 6:51 am
Ubicación: Cuenca

Re: Un ROV de agua dulce, con mando de PS2

Mensaje por asesorplaza1 »

Código Esclavo

Código: Seleccionar todo

// Se ponen todas las librerías juntas

#include <Servo.h>              // librería para gestionar los servos y los ESC
#include <EasyTransfer.h>       // librería Easy Transfer de Bill Porter
#include <Adafruit_Sensor.h>    // librería para gestionar el sensor de temperatura DHT22
#include <DHT.h>                // librería para el sensor DHT 22
#include <OneWire.h>            // librería para el sensor de temperatura DS18B20
#include <DallasTemperature.h>  // Librería para el sensor de temperatura DS18B20
#include <MPU6050.h>            // librería i2c para el Giroscopio ***
#include <PS2X_lib.h>           // Librería para el mando PS2
#include <ESC.h>                // Librería para los ESC

PS2X ps2x;                          // Genera un objeto llamado ps2x
EasyTransfer ETin, ETout;           // Genera los dos objetos de transferencia fácil para Comunicación bidireccional

const int pinDatosDQ = 28;                       // Pin donde se conecta el bus 1-Wire para los sensores de temperatura
OneWire oneWireObjeto(pinDatosDQ);               // Instancia a las clases OneWire y DallasTemperature
DallasTemperature sensorDS18B20(&oneWireObjeto); // Instancia a las clases OneWire y DallasTemperature

// #define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))

// Se pone toda la identificación de los DHT22 junta

DHT dht(22, DHT22);    // Seleccionamos el pin y tipo de sensor del casco
DHT dht1(24, DHT22);   // Seleccionamos el pin y tipo de sensor del motor derecho
DHT dht2(26, DHT22);   // Seleccionamos el pin y tipo de sensor del motor izquierdo

// Se pone toda la identificación de los ESC y los Servos junta

ESC ESCVL(8, 1000, 2000, 500);           // Genera objeto ESC vertical izquierdo en el pin 8, con el minimo en 1000, maximo en 2000, y armado en 500
ESC ESCVR(7, 1000, 2000, 500);           // Genera objeto ESC vertical derecho en el pin 7, con el minimo en 1000, maximo en 2000, y armado en 500
ESC ESCHL(6, 1000, 2000, 500);           // Genera Objeto ESC Horizontal Izquierdo en el pin 6, con el minimo en 1000, maximo en 2000, y armado en 500
ESC ESCHR(5, 1000, 2000, 500);           // Genera objeto ESC Horizontal Derecho, en el pin 5, con el minimo en 1000, maximo en 2000, y armado en 500
Servo ServoInmersion;           // Genera un objeto llamado ServoDireccion
int angulo = 90;                // Variable para el ángulo, inicia en 90º

// Se pone toda la identificación de los LED indicadores de batería junta

const int RedLEDpin = 13;  // El pin del indicador LED es 13.
const int HeadLts = 34;    // El control de los faros está en el pin 34
const int Voltpin = A7;    // pin analógico utilizado para leer el voltaje de la batería
const int yelLEDpin = 38;  // Pin utilizado como chivato de recibir datos del mando

// Se pone toda la identificación del sistema de refrigeración junta

const int Refrigeracion = 34; // el pin utilizado para encender la bomba de refrigeración es el 34
const int TwarnLEDpin = 36;   // El pin utilizado para el LED de alarma de temperatura es el 36

// Se pone toda la identificación del MPU6050 junta

const int MPU6050_addr = 0x68; // Direction I2C del MPU6050
int16_t AccX, AccY, AccZ, Temp, GyroX, GyroY, GyroZ;

// Se pone toda la parte de lectura de la batería junta

int volts;                          // variable para leer el voltaje del pin analógico
const float RefVolts = 5.0;         // Voltaje de referencia de la placa de 5 voltios en Nano
const float ResistFactor = 319.68;  // Calculado a partir de 1023.0 * (R2 / (R1 + R2)
// Donde R1 = 2200 ohmios y R2 = 1000 ohmios para un voltaje máximo de 15 V.

// Se pone toda la parte del sensor E18D80NK

int pinSensorE18D80NK = 30;   // Se genera el sensor E18D80NK en el pin 30
int pinLedColision = 31;      // Se genera el LED de aviso de peligro colisión en el pin 31
boolean objectDetect = false; // Marca para mostrar si se ha detectado un objeto

// Se generan todos los botones del mando

boolean PSB_PAD_UPstate = false;     // Genera el botón Izquierda arriba al Esclavo
boolean PSB_PAD_DOWNstate = false;   // Genera el botón Izquierda abajo al Esclavo
boolean PSB_PAD_LEFTstate = false;   // El botón Izquierda izquierdo ya esta usado para encender los focos
boolean PSB_PAD_RIGHTstate = false;  // Genera el botón Izquierda derecho al Esclavo
boolean PSB_BLUEstate = false;       // Genera el botón Cruz azul al Esclavo
boolean PSB_GREENstate = false;      // Genera el botón Triangulo verde al Esclavo
boolean PSB_PINKstate = false;       // Genera el botón Cuadrado rosa al Esclavo
boolean PSB_REDstate = false;        // Genera el botón Circulo rojo al Esclavo
boolean PSB_L1state = false;         // Genera el botón Izquierda delante arriba al Esclavo
boolean PSB_L2state = false;         // Genera el botón Izquierda delante abajo al Esclavo
boolean PSB_L3state = false;         // Genera el botón Palo izquierdo abajo al Esclavo
boolean PSB_R1state = false;         // Genera el botón Derecha delante arriba al Esclavo
boolean PSB_R2state = false;         // Genera el botón Derecha delante abajo al Esclavo
boolean PSB_R3state = false;         // Genera el botón Palo derecho abajo al Esclavo

// Se genera un pin de entrada de datos para el sensor de presión SKU237545

int SensorSKU237545_I = 32;  // Sensor de presión Interno
int SensorSKU237545_E = 33;  // Sensor de presión Externo

int intervalodatos = 1000;  // Hace que solo se envíen los valores 1 vez por segundo
// int auxMillis = 0;          // Indica el valor del intervalo de tiempo

// Se pone toda la estructura de recepción de datos junta

struct RECEIVE_DATA_STRUCTURE {
  int upLraw = 0;   // Variables para transportar los datos sin procesar reales de los ESC
  int upRraw = 0;
  int HLraw = 0;
  int HRraw = 0;
  volatile boolean PSB_PAD_UPstate;     // Recibe lectura del botón Izquierda arriba del Maestro
  volatile boolean PSB_PAD_DOWNstate;   // Recibe lectura del botón Izquierda abajo del Maestro
  volatile boolean PSB_PAD_RIGHTstate;  // Recibe lectura del botón Izquierda derecha del Maestro
  volatile boolean PSB_PAD_LEFTstate;   // Recibe lectura del botón Izquierda Izquierda del Maestro
  volatile boolean PSB_BLUEstate;       // Recibe lectura del botón Cruz azul del Maestro
  volatile boolean PSB_GREENstate;      // Recibe lectura del botón Triangulo verde del Maestro
  volatile boolean PSB_PINKstate;       // Recibe lectura del botón Cuadrado rosa del Maestro
  volatile boolean PSB_REDstate;        // Recibe lectura del botón Circulo rojo del Maestro
  volatile boolean PSB_L1state;         // Recibe lectura del botón Delante izquierda arriba del Maestro
  volatile boolean PSB_L2state;         // Recibe lectura del botón Delante izquierda abajo del Maestro
  volatile boolean PSB_L3state;         // Recibe lectura de presión Palo izquierda del Maestro
  volatile boolean PSB_R1state;         // Recibe lectura del botón Delante derecha arriba del Maestro
  volatile boolean PSB_R2state;         // Recibe lectura del botón Delante derecha abajo del Maestro
  volatile boolean PSB_R3state;         // Recibe lectura de presión Palo izquierdo del Maestro
  volatile boolean LEDHdlts;            // Luces LED encendidas / apagadas
};

// Se pone toda la identificación del envío de datos junta

struct  SEND_DATA_STRUCTURE {
  int BattVolt;             // Manda mensaje de datos de voltaje de batería al maestro.
  int t;                    // Manda mensaje de datos de temperatura interior del ROV al Maestro
  int t1;                   // Manda mensaje de datos de temperatura del motor derecho al Maestro
  int t2;                   // Manda mensaje de datos de temperatura del motor izquierdo al Maestro
  int ROVDepth;             // Manda mensaje de datos de lectura de profundidad de ROV (m)
  int ROVHDG;               // Manda mensaje de Dirección del ROV (grados)
  int h;                    // Manda mensaje de humedad al Maestro
  int h1;                   // Manda mensaje de humedad al Maestro del motor derecho
  int h2;                   // Manda mensaje de humedad al Maestro del motor izquierdo
  int AccX;                 // Manda mensaje de datos de inclinación del eje X al Maestro
  int AccY;                 // Manda mensaje de datos de inclinación del eje Y al Maestro
  int AccZ;                 // Manda mensaje de datos de de inclinación del eje Z al Maestro
  int Temp;                 // Manda mensaje de datos de temperatura del giroscopio al Maestro
  int GyroX;                // Manda mensaje de datos de aceleración en el eje X al Maestro
  int GyroY;                // Manda mensaje de datos de aceleración en el eje Y al Maestro
  int GyroZ;                // Manda mensaje de datos de aceleración en el eje Z al Maestro
  int E18D80NK;             // Manda mensaje de lectura del sensor infrarrojo E18-D80NK
  int pinLedColision;       // Manda mensaje de encender alarma de colisión
  int sensorDS18B20;        // Manda mensaje de lectura del sensor de temperatura DS18B20
  int pressure_bar;         // Manda mensaje de lectura del sensor de presión SKU237545 Interno en Bares
  int pressure_psi;         // Manda mensaje de lectura del sensor de presión SKU237545 Interno en PSI
  int pressure_bar1;        // Manda mensaje de lectura del sensor de presión SKU237545 Interno en Bares
  int pressure_psi1;        // Manda mensaje de lectura del sensor de presión SKU237545 Interno en PSI
};

RECEIVE_DATA_STRUCTURE rxdata; // Dar un nombre al grupo de datos recibidos
SEND_DATA_STRUCTURE txdata;    // Dar un nombre al grupo de datos enviados

void setup()
{

  // Se pone todo lo referente a la comunicación junta

  Wire.begin ();                           // Comienza la comunicación i2c

  Serial.begin(9600);                       // Comienza la Comunicación Serie para hablar con el ordenador a 9600 baudios
  Serial1.begin(115200);                     // Comienza la Comunicación Serie en el puerto 1, pines 18 y 19, para hablar con el Arduino Maestro
  Serial1.flush();                         // Depura la información del Puerto Serie
  ETin.begin(details(rxdata), & Serial1);  // Comienza la recepción de datos a través de Serial, en los pines 18 y 19
  ETout.begin(details(txdata), & Serial1); // Comienza el envío de datos a través de Serial, en los pines 18 y 19
  sensorDS18B20.begin();                   // Comienza el trabajo del sensor DS18B20

  // Se define el inicio del LED y de los Focos

  pinMode(RedLEDpin, OUTPUT);
  pinMode(HeadLts, OUTPUT);
  digitalWrite(HeadLts, LOW);  // Establezca los faros en Off
  digitalWrite(RedLEDpin, LOW);

  // Se inician los ESC y se define en que pin actúa cada uno
  ESCVL.arm();         // Inicia el ESCVL
  ESCVR.arm();         // Inicia el ESCVR
  ESCHL.arm();         // Inicia el ESCHL
  ESCHR.arm();         // Inicia el ESCHR

  // Esto hay que comprobarlo
  // Debido a problemas con el ESC que reconoce el máximo posición en la configuración predeterminada, las cifras después de
  // El número de pin son las señales de microsegundos para el mínimo y máximo que el ESC reconocerá, 600 y 2250 trabajo.

  ServoInmersion.attach(4); // Adjunte el servo de dirección al pin 4
  ServoInmersion.write(90); // Posiciona el servo inicialmente en la mitad (90°)

  // Se inician y se manda a imprimir la prueba de funcionamiento de los sensores DHT22
  dht.begin();  // Inicia el trabajo del sensor DHT22 del casco
  Serial.println (F(" \n Probando sensor DHT22 casco!"));
  dht1.begin(); // Inicia el trabajo del sensor DHT22 del motor derecho
  Serial.println (F(" \n Probando sensor DHT22 motor DR!"));
  dht2.begin(); // Inicia el trabajo del sensor DHT22 del motor izquierdo
  Serial.println (F(" \n Probando sensor DHT22 motor IZ!"));

  // Se inician los pines del sensor y de la alarma
  pinMode(pinSensorE18D80NK, INPUT_PULLUP); // Definir pin como sensor de entrada
  pinMode(pinLedColision, OUTPUT); // Definir pin como SALIDA para ACTION

  // Se inicia el pin del sensor de presión SKU237545 Interno
  pinMode (SensorSKU237545_I, INPUT);

  // Se inicia el pin del sensor de presión SKU237545 Externo
  pinMode (SensorSKU237545_E, INPUT);

  // Proceso para iniciar el giroscopio MPU6050
  Wire.begin();
  Wire.beginTransmission(MPU6050_addr);
  Wire.write(0x6B);
  Wire.write(0);
  Wire.endTransmission(true);

  delay (200);
}

void loop ()
{

  for (int i = 0; i < 5; i++) {

    ETin.receiveData();    // Recibe los datos al puerto serie para el ROV

    Serial.print (F("\n Datos recibidos del Meastro.."));

    loop_ESC();             // Bloque de trabajo de los ESC de los motores
    loop_Luces();           // Bloque de trabajo de los focos
    loop_Voltaje();         // Bloque de trabajo para medir el voltaje de la batería
    loop_DHT22();           // Bloque de trabajo de los sensores de temperatura y humedad DHT22
    loop_MPU6050();         // Bloque de trabajo del Giroscopio
    loop_SensorE18D80NK();  // Bloque de trabajo del sensor de infrarrojos
    loop_DS18B20();         // Bloque de trabajo del sensor de temperatura DS18B20
    loop_SKU237545_I();     // Bloque de trabajo del sensor de presión interno
    loop_SKU237545_E();     // Bloque de trabajo del sensor de presión externo
    loop_ServoInmersion();  // Bloque de trabajo del servo

    PSB_PAD_UPstate = (rxdata.PSB_PAD_UPstate);         // Recibe lectura del botón Izquierda arriba al Esclavo
    PSB_PAD_DOWNstate = (rxdata.PSB_PAD_DOWNstate);     // Recibe lectura del botón Izquierda abajo al Esclavo
    PSB_PAD_LEFTstate = (rxdata.PSB_PAD_LEFTstate);     // Recibe lectura del botón Izquierda Izquierda al Esclavo
    PSB_PAD_RIGHTstate = (rxdata.PSB_PAD_RIGHTstate);   // Recibe lectura del botón Izquierda derecho al Esclavo
    PSB_BLUEstate = (rxdata.PSB_BLUEstate);             // Recibe lectura del botón Cruz azul al Esclavo
    PSB_GREENstate = (rxdata.PSB_GREENstate);           // Recibe lectura del botón Triangulo verde al Esclavo
    PSB_PINKstate = (rxdata.PSB_PINKstate);             // Recibe lectura del botón Cuadrado rosa al Esclavo
    PSB_REDstate = (rxdata.PSB_REDstate);               // Recibe lectura del botón Circulo rojo al Esclavo
    PSB_L1state = (rxdata.PSB_L1state);                 // Recibe lectura del botón Izquierda delante arriba al Esclavo
    PSB_L2state = (rxdata.PSB_L2state);                 // Recibe lectura del botón Izquierda delante abajo al Esclavo
    PSB_L3state = (rxdata.PSB_L3state);                 // Recibe lectura del botón Palo izquierdo abajo al Esclavo
    PSB_R1state = (rxdata.PSB_R1state);                 // Recibe lectura del botón Derecha delante arriba al Esclavo
    PSB_R2state = (rxdata.PSB_R2state);                 // Recibe lectura del botón Derecha delante abajo al Esclavo
    PSB_R3state = (rxdata.PSB_R3state);                 // Recibe lectura del botón Palo derecho abajo al Esclavo

    // No me deja generar un bloque de trabajo para los botones del mando
    // Por eso los pongo dentro del void loop genérico

    if (rxdata.PSB_PAD_UPstate)
      // Si presionamos el botón izquierda arriba
    {
      digitalWrite(yelLEDpin, HIGH);
      // Enciende el Led Amarillo
    }

    if (rxdata.PSB_PAD_DOWNstate)
      // Si presionamos el botón izquierda abajo
    {
      digitalWrite(yelLEDpin, HIGH);
      // Enciende el Led Amarillo
    }

    if (rxdata.PSB_PAD_RIGHTstate)
      // Si presionamos el botón izquierda derecha
    {
      digitalWrite(yelLEDpin, HIGH);
      // Enciende el Led Amarillo
    }

    if (rxdata.PSB_GREENstate)
      // Si presionamos triangulo verde
    {
      digitalWrite(yelLEDpin, HIGH);
      // Enciende el Led Amarillo
    }

    if (rxdata.PSB_REDstate)
      // Si presionamos el círculo rojo
    {
      digitalWrite(yelLEDpin, HIGH);
      // Enciende el Led Amarillo
    }

    if (rxdata.PSB_BLUEstate)
      // Si presionamos el cruz azul
    {
      digitalWrite(yelLEDpin, HIGH);
      // Enciende el Led Amarillo
    }

    if (rxdata.PSB_PINKstate)
      // Si presionamos el cuadrado rosa
    {
      digitalWrite(yelLEDpin, HIGH);
      // Enciende el Led Amarillo
    }

    if (rxdata.PSB_L1state)
      // Si presionamos el botón L1
    {
      digitalWrite(yelLEDpin, HIGH);
      // Enciende el Led Amarillo
    }

    if (rxdata.PSB_L2state)
      // Si presionamos el botón L2
    {
      digitalWrite(yelLEDpin, HIGH);
      // Enciende el Led Amarillo
    }

    if (rxdata.PSB_R1state)
      // Si presionamos el botón R1
    {
      // Enciende / apaga las luces
      digitalWrite(yelLEDpin, HIGH);
      // Enciende el Led Amarillo
    }

    if (rxdata.PSB_R2state)
      // Si presionamos el botón R2
    {
      // Enciende / apaga las luces
      digitalWrite(yelLEDpin, HIGH);
      // Enciende el Led Amarillo
    }

    if (rxdata.PSB_L3state)
      // Si presionamos el joystick izquierdo hacia abajo
    {
      digitalWrite(yelLEDpin, HIGH);
      // Enciende el Led Amarillo
    }

    if (rxdata.PSB_R3state)
      // Si presionamos el joystick derecho hacia abajo
    {
      digitalWrite(yelLEDpin, HIGH);
      // Enciende el LED Amarillo
    }

  }
}
void loop_ESC() { // Bloque de trabajo de los ESC de los motores

  // Haremos algo correctamente con los datos devueltos en un
  ESCVL.speed(rxdata.upLraw);   // Establezca la señal ESCVL en la posición del acelerador definida.
  ESCVR.speed(rxdata.upRraw);   // Establezca la señal ESCVR en la posición del acelerador definida.
  ESCHL.speed(rxdata.HLraw);    // Establezca la señal ESCHL en la posición del acelerador definida.
  ESCHR.speed(rxdata.HRraw);    // Establezca la señal ESCHR en la posición del acelerador definida.

}

void loop_ServoInmersion() {         // Bloque de trabajo del Servo de Inmersión

  if (rxdata.PSB_R1state == LOW)
    // Aumenta el ángulo mientras se mantenga presionado
  {
    angulo++;
    if (angulo >= 180)
    {
      angulo = 180;
      // El ángulo no aumenta más allá de 180 grados
      Serial.print (F(" \n Subiendo ROV a superficie "));
    }
  }
  else if (rxdata.PSB_R2state == LOW)
    // Disminuye el ángulo mientras se mantenga presionado
  {
    angulo--;
    if (angulo <= 0)
    {
      angulo = 0;
      // El ángulo no disminuye mas allá de 0 grados
      Serial.print (F("\n Inmersion ROV a profundidad "));
    }
  }
  ServoInmersion.write(angulo);
  // Manda el ángulo al servo dependiendo del pulsador presionado
  //  delay(10);
}

void loop_Luces() { // Bloque de trabajo de los focos
  digitalWrite(HeadLts, rxdata.LEDHdlts);
  // Enciende los faros en función del retraso de los datos del mensaje
  if (rxdata.LEDHdlts > 0) {
    digitalWrite(HeadLts, LOW);
    Serial.print (F(" \n Focos apagados "));
  }
  else {
    (rxdata.LEDHdlts < 0);
    digitalWrite(HeadLts, HIGH);
    Serial.print (F(" \n Focos encendidos "));
  }
}

void loop_Voltaje() { // Bloque de trabajo de medición de voltaje de la batería

  volts = analogRead(Voltpin) / ResistFactor * RefVolts * 10; // Lee el voltaje
  // De la batería a través del divisor de voltaje. Factor de 10 utilizado
  // Para ayudar a lograr un número entero con una precisión de 0.1V.
  // Factor 10 utilizado para obtener precisión adicional del valor entero y luego se muestra con 1 decimal
  txdata.BattVolt = volts;  // Enviar de vuelta el voltaje de la batería a bordo.
  Serial.print (F(" \n Voltaje del ROV = "));
  Serial.print(volts);

}

void loop_DHT22() { // Bloque de trabajo de los sensores DHT22

  float h = dht.readHumidity();
  // Lectura de Humedad desde el sensor DHT22 del interior del ROV
  float t = dht.readTemperature();
  // Lectura de Temperatura desde el sensor DHT22 del interior del ROV
  float h1 = dht1.readHumidity();
  // Lectura de Humedad desde el sensor DHT22 del motor derecho
  float t1 = dht1.readTemperature();
  // Lectura de Temperatura desde el sensor DHT22 del motor derecho
  float h2 = dht2.readHumidity();
  // Lectura de Humedad desde el sensor DHT22 del motor izquierdo
  float t2 = dht2.readTemperature();
  // Lectura de Temperatura desde el sensor DHT22 del motor izquierdo
  int intervaloMedidas = 1000;
  // Hace que solo se lean los valores 1 vez por segundo
  unsigned long auxMillis = 0;
  // Indica el valor del intervalo de tiempo

  // Comprueba si hay fallo en todas las lecturas y sale rápido y prueba otra vez
  if (isnan(h) || isnan(t)) {
    Serial.print (F(" \n Fallo de lectura desde el sensor DHT del Casco!"));
    return;
  }
  else if (isnan(h1) || isnan(t1)) {
    Serial.print (F(" \n Fallo de lectura desde el sensor DHT del motor DR!"));
    return;
  }
  else if (isnan(h2) || isnan(t2)) {
    Serial.print (F(" \n Fallo de lectura desde el sensor DHT del motor IZ!"));
    return;
  }
  else if (( millis() - auxMillis) > intervaloMedidas) {
    txdata.t = t;   // Envía al Maestro la temperatura leída en el casco
    txdata.h = h;   // Envía al Maestro la humedad leída en el casco
    txdata.t1 = t1; // Envía al Maestro la temperatura leída en el motor derecho
    txdata.h1 = h1; // Envía al Maestro la humedad leída en el motor derecho
    txdata.t2 = t2; // Envía al Maestro la temperatura leída en el motor izquierdo
    txdata.h2 = h2; // Envía al Maestro la humedad leída en el motor izquierdo
    auxMillis = millis();
  }
  else if (t > 40 || t1 > 40 || t2 > 40)
  {
    // Si la temperatura de cualquiera de los sensores DHT22 es demasiado alta (más de 40 grados C)
    // Enciende el LED de advertencia
    digitalWrite(TwarnLEDpin, HIGH);
    // Enciende la bomba de refrigeración
    digitalWrite(Refrigeracion, HIGH);
    // Escribe el texto
    Serial.print (F(" \n TEMPERATURA ELEVADA !"));
  }
  Serial.print (F(" \n Temperatura en el casco = "));
  Serial.print (t);
  Serial.print (F(" *C "));
  Serial.print (F(" \n Temperatura en el motor DR = "));
  Serial.print (t1);
  Serial.print (F(" *C1 "));
  Serial.print (F(" \n Temperatura en el motor IZ = "));
  Serial.print (t2);
  Serial.print (F(" *C2 "));
  Serial.print (F(" \n Humedad en el Casco = "));
  Serial.print (h);
  Serial.print (F(" %\t"));
  Serial.print (F(" \n Humedad en el motor DR = "));
  Serial.print (h1);
  Serial.print (F(" %\t"));
  Serial.print (F(" \n Humedad en el motor IZ = "));
  Serial.print (h2);
  Serial.print (F(" %\t"));

}

void loop_MPU6050() {  // Bloque de trabajo del giroscopio

  Wire.beginTransmission(MPU6050_addr);
  Wire.write(0x3B);
  Wire.endTransmission(false);
  Wire.requestFrom(MPU6050_addr, 14, true);
  AccX = Wire.read() << 8 | Wire.read();
  AccY = Wire.read() << 8 | Wire.read();
  AccZ = Wire.read() << 8 | Wire.read();
  Temp = Wire.read() << 8 | Wire.read();
  GyroX = Wire.read() << 8 | Wire.read();
  GyroY = Wire.read() << 8 | Wire.read();
  GyroZ = Wire.read() << 8 | Wire.read();

  txdata.AccX = AccX;
  txdata.AccY = AccY;
  txdata.AccZ = AccZ;
  txdata.Temp = Temp;
  txdata.GyroX = GyroX;
  txdata.GyroY = GyroY;
  txdata.GyroZ = GyroZ;

  Serial.print (F(" \n Inclinación del eje X del ROV = "));
  Serial.print (AccX);
  Serial.print (F(" \n Inclinación del eje Y del ROV = "));
  Serial.print (AccY);
  Serial.print (F(" \n Inclinación del eje Z del ROV = "));
  Serial.print (AccZ);
  Serial.print (F(" \n Temperatura del Giro MPU6050 = "));
  Serial.print (Temp / 340.00 + 36.53);
  Serial.print (F(" \n Aceleración del Giro MPU6050 = "));
  Serial.print (GyroX);
  Serial.print (F(" \n Aceleración del Giro MPU6050 = "));
  Serial.print (GyroY);
  Serial.print (F(" \n Aceleración del Giro MPU6050 = "));
  Serial.print(GyroZ);

  // Serial.print(" \n Dirección del ROV = ");
  //  Serial.print(rxdata.ROVHDG);  // muestra la dirección del ROV en una brújula

  Wire.endTransmission(MPU6050_addr); //

}

void loop_SensorE18D80NK() { // Bloque de trabajo del sensor infrarrojo

  int E18D80NK = digitalRead(pinSensorE18D80NK); // leer el Sensor

  if (E18D80NK > 0) {
    Serial.println (F(" \n Todo despejado"));
    digitalWrite(pinLedColision, LOW); // encender el LED de peligro
  }
  else {
    Serial.println (F(" \n Peligro Objeto detectado"));
    digitalWrite(pinLedColision, HIGH); // Apagar el LED de peligro
  }
  txdata.E18D80NK = E18D80NK;
}

void loop_DS18B20() {  // Bloque de trabajo del sensor de temperatura DS18B20

  sensorDS18B20.requestTemperatures();
  Serial.print (F("\n Temperatura sensor DS18B20 = "));
  Serial.print (sensorDS18B20.getTempCByIndex(0));
  Serial.print (F(" ºC"));
  txdata.sensorDS18B20 = sensorDS18B20.getTempCByIndex(0);
}

void loop_SKU237545_I() { // Bloque de trabajo del sensor de presión interno

  SensorSKU237545_I = analogRead(32);
  float voltage = (SensorSKU237545_I * 5.0) / 1024.0;
  float pressure_pascal = (3.0 * ((float)voltage - 0.475)) * 1000000.0;  //calibrar aquí
  float pressure_bar = pressure_pascal / 10e5;
  float pressure_psi = pressure_bar * 14.5038;
  Serial.print (F(" \n Valor del Sensor de Presión Interno =  "));
  Serial.print (SensorSKU237545_I);
  Serial.print (F(" \n Presión en Bar = "));
  Serial.print (pressure_bar);
  Serial.print (F("    bars"));
  Serial.print (F(" \n Presión en PSI = "));
  Serial.print (pressure_psi);
  Serial.print (F("   psi"));
  txdata.pressure_bar = pressure_bar;
  txdata.pressure_psi = pressure_psi;
}

void loop_SKU237545_E() {  // bloque de trabajo del sensor de presión externo

  SensorSKU237545_E = analogRead(32);
  float voltage1 = (SensorSKU237545_E * 5.0) / 1024.0;
  float pressure_pascal1 = (3.0 * ((float)voltage1 - 0.475)) * 1000000.0;  //calibrar aquí
  float pressure_bar1 = pressure_pascal1 / 10e5;
  float pressure_psi1 = pressure_bar1 * 14.5038;
  Serial.print (F(" \n Valor del Sensor de Presión Externo = "));
  Serial.print (SensorSKU237545_E);
  Serial.print (F(" Presión en Bar = "));
  Serial.print (pressure_bar1);
  Serial.print (F("    bars"));
  Serial.print (F(" \n Presión en PSI = "));
  Serial.print (pressure_psi1);
  Serial.print (F("   psi"));
  Serial.print (F(" \n Profundidad = "));
  txdata.pressure_bar1 = pressure_bar1;
  txdata.pressure_psi1 = pressure_psi1;

  // Serial.print(rxdata.ROVDepth);
  // Muestra en el Display la profundidad del ROV en metros


  ETout.sendData ();     // Envía los datos al puerto serie para el ROV Arduino

}
asesorplaza1
Colaborador
Colaborador
Mensajes: 209
Registrado: Jue Ene 24, 2019 6:51 am
Ubicación: Cuenca

Re: Un ROV de agua dulce, con mando de PS2

Mensaje por asesorplaza1 »

Y aquí os pongo los códigos comprimidos.

Un saludo.
Adjuntos
51_16_05_2020.rar
Códigos comprimidos
(16.39 KiB) Descargado 74 veces
Avatar de Usuario
tsanshon
Colaborador
Colaborador
Mensajes: 169
Registrado: Mié Jul 29, 2009 1:36 am
Ubicación: Bilbao

Re: Un ROV de agua dulce, con mando de PS2

Mensaje por tsanshon »

Hola AP1.

He revisado el código y veo varias cosas que pueden hacer que la comunicación no funcione.

En el maestro:

Código: Seleccionar todo

260 unsigned long a = millis();  // Se define y se inicia una variable llamada millis

262 void setup() {

  Serial.begin(9600);      // Comienza la Comunicación en Serie para hablar con el ordenador a 9600 Baudios
  Serial1.begin(9600);    // Comienza la comunicación Serie en el puerto 1, pines 18 y 19, para hablar con el Arduino Esclavo
  Serial1.flush();         // Depura la información del Puerto Serie
  ETin.begin(details(rxdata), &Serial1);    // Comienza la recepción de datos a través de Serial, en los pines 18 y 19
  ETout.begin(details(txdata), &Serial1);   // Comienza el envío de datos a través de Serial, en los pines 18 y 19
  // Resto de código del setup
278  error = ps2x.config_gamepad(22, 23, 24, 25, false, false);
  // Resto de código del setup
}

298 void loop()
    {
301   if (millis() > a + 100)
      {
304     if (error == 0)
        {
          // Código que lee el estado del mando y actualiza las variables de txdata
        }
445     ETout.sendData(); // Enviar el mensaje al puerto serie para el Arduino del ROV
447     for (int i = 0; i < 5; i++)
        {
449       a = millis();
        }
452     if (ETin.receiveData())    // Recibe el mensaje al puerto serie para el Arduino del ROV
        {
          // Codigo para presentar datos en pantalla a través del puerto Serial
        }
      }
    }
El if de la linea 452 tiene que estar fuera de la temporización para que se ejecute en cuanto tenga un mensaje.
El bucle for de la línea 447 asigna el tiempo actual a la variable a 5 veces seguidas. No tiene sentido. Se elimina el bucle for
Es recomendable dar nombres descriptivos a las variables para facilitar la comprensión del código, por ejemplo la variable "a" podría ser "temporMsg".
Maestro revisado:

Código: Seleccionar todo

298 void loop()
    {
301   if (millis() > a + 100)
      {
304     if (error == 0)
        {
          // Código que lee el estado del mando y actualiza las variables de txdata
        }
445     ETout.sendData(); // Enviar el mensaje al puerto serie para el Arduino del ROV
449     a = millis();
      }
452   if (ETin.receiveData())    // Recibe el mensaje al puerto serie para el Arduino del ROV
      {
        // Codigo para presentar datos en pantalla a través del puerto Serial
      }
    }
En el caso del esclavo:

Código: Seleccionar todo

306 void setup()
    {
      // Se pone todo lo referente a la comunicación junta
      Wire.begin ();                           // Comienza la comunicación i2c
      Serial.begin(9600);                       // Comienza la Comunicación Serie para hablar con el ordenador a 9600 baudios
314   Serial1.begin(115200);                     // Comienza la Comunicación Serie en el puerto 1, pines 18 y 19, para hablar con el Arduino Maestro
      Serial1.flush();                         // Depura la información del Puerto Serie
      ETin.begin(details(rxdata), & Serial1);  // Comienza la recepción de datos a través de Serial, en los pines 18 y 19
      ETout.begin(details(txdata), & Serial1); // Comienza el envío de datos a través de Serial, en los pines 18 y 19
      // resto código setup
    }

368 void loop ()
    {
371   for (int i = 0; i < 5; i++) 
      {
373     ETin.receiveData();    // Recibe los datos al puerto serie para el ROV
        // Resto código loop
      }
    }
748  ETout.sendData ();     // Envía los datos al puerto serie para el ROV Arduino
Linea 314: La velocidad de transmisión tiene que ser igual en el maestro y en el esclavo por defecto 9600 baudios. Si no, no funciona.
Línea 371: El bucle for ejecuta 5 veces seguidas el código. ¿Para qué?. La función receiveData() devuelve 1 cuando hay un mensaje disponible. Cambiando el bucle for por la condición if (ETin.receiveData()) el código dentro del if solo se ejecuta cuando hay un mensaje nuevo.
Línea 748: El código para enviar el mensaje al maestro esta dentro de la función loop_SKU237545_E() que gestiona el sensor de presión y que a su vez esta dentro del bucle for por lo que se envian 5 mensajes seguidos al maestro. Se elimina el bucle for y se pone el codigo para enviar el mensaje al final del if (ETin.receiveData()).
Esclavo revisado:

Código: Seleccionar todo

368 void loop ()
    {
371   if (ETin.receiveData()) 
      {
373     // Resto código
        ETout.sendData (); // Envía los datos al puerto serie para el ROV Arduino
      }
    }

Espero que con estos cambios estés un poco mas cerca de que funcione. Hay otras cosas que he visto, pero hablaremos mas adelante, cuando tengas operativa la comunicación.


Un saludo.
Alberto.
asesorplaza1
Colaborador
Colaborador
Mensajes: 209
Registrado: Jue Ene 24, 2019 6:51 am
Ubicación: Cuenca

Re: Un ROV de agua dulce, con mando de PS2

Mensaje por asesorplaza1 »

Buenas noches.

Muchas gracias Alberto.

Después de unos días complicados de trabajo, he podido revisar los códigos según las recomendaciones de Tsanshon, y los adjunto.

La verdad es que me he sentido un poco perdido, después de unos días sin leer los códigos, y he tenido que leer las explicaciones de Alberto varias veces, pero ya lo he conseguido.

Lo que me gustaría saber, es como llega Alberto a esas conclusiones, pero aun así, estoy dispuesto a seguir arreglando el programa.

Muchas gracias otra vez.

Un saludo
Adjuntos
52_29_05_2020.rar
(16.29 KiB) Descargado 87 veces
Avatar de Usuario
tsanshon
Colaborador
Colaborador
Mensajes: 169
Registrado: Mié Jul 29, 2009 1:36 am
Ubicación: Bilbao

Re: Un ROV de agua dulce, con mando de PS2

Mensaje por tsanshon »

Hola asesorplaza1.

He intentado darte las pautas para que puedas adaptar la forma en que se comunica el maestro con el esclavo a como lo he hecho yo en el proyecto del Damen multi cat 1205 que funciona perfectamente:

La idea es que el esclavo solo transmite un mensaje cada vez que recibe uno del maestro, de esta forma transmitiendo periódicamente un mensaje al esclavo desde el maestro la comunicación se mantiene sincronizada.

Como comprenderás, no puedo mas que hacerte sugerencias de como lo haría yo.


Animo.

Alberto.
Responder