Se interrumpe el puerto COM de mi porgrama usando Java con librerias RXTX

Hola, pues en la prepa me pidieron que si les hacia un programa para automatizar los timbres de cada clase, hice un programa en java usando la libreria RXTX para la comunicacion serial con Arduino, uso un arduino y un modulo relay conectado a la campana de los timbres, mi codigo de java es el siguiente (pondre la parte donde envia datos a Arduino y de la comunicacion serial, porque no veo sentido mandar el hilo del reloj o el de la fecha)
Comunicacion serial de libreria RXTX

 private static final String Turn_LED_Off = "0";
    private static final String Turn_LED_On = "1";
   

    
    // Variables de conexion
    private OutputStream output = null;
    SerialPort serialPort;
    private final String puerto = "COM3";
    private final String puerto1 = "COM4"; //poner nombre del puerto COM
    private static final int timeout = 2000; // milisegundos
    private static final int data_Rate = 9600;

 public void InicializarConexion(){
       CommPortIdentifier puertoId = null;
        Enumeration puertoEnum = CommPortIdentifier.getPortIdentifiers();
        while (puertoEnum.hasMoreElements()){
            CommPortIdentifier actualPortId = (CommPortIdentifier) puertoEnum.nextElement();
            if (puerto.equals(actualPortId.getName())){
                puertoId = actualPortId;
                break;
            }
            if (puerto1.equals(actualPortId.getName())){
                puertoId = actualPortId;
                break;
            }
        }
        if (puertoId==null){
            mostrarError("No se puede conectar al puerto");
            System.exit(ERROR);
            
        }
     
        try{
        serialPort = (SerialPort) puertoId.open(this.getClass().getName(), timeout); 
//parametros puerto serial
        serialPort.setSerialPortParams(data_Rate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
        output = serialPort.getOutputStream();
        }
        catch(Exception e){
            mostrarError(e.getMessage());
            System.exit(ERROR);
        }
   
    }
           private void enviarDatos(String datos){
               try{
                   output.write(datos.getBytes());
                   
               } catch(Exception e){
                   mostrarError("Error");
                   System.exit(ERROR);
               }
           }
           public void mostrarError(String mensaje){
               JOptionPane.showMessageDialog(this, mensaje, "Error", JOptionPane.ERROR_MESSAGE);

Envia datos

 String yolo = formato.format(hoy);
       
           if(yolo.equals("06:55:00 AM") || yolo.equals("07:00:00 AM") || yolo.equals("07:50:00 AM") || yolo.equals("08:40:00 AM") || yolo.equals("09:25:00 AM") || yolo.equals("10:00:00 AM") || yolo.equals("10:05:00 AM") || yolo.equals("10:50:00 AM") || yolo.equals("11:40:00 AM") || yolo.equals("12:30:00 PM") || yolo.equals("12:40:00 PM") || yolo.equals("01:30:00 PM") || yolo.equals("02:20:00 PM")) {
           enviarDatos(Turn_LED_On);
        
        }

codigo arduino

const int led = 13;
int ByteIn = 0;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(led, OUTPUT);
  digitalWrite(led, LOW);
  

}

void loop() {
  // put your main code here, to run repeatedly:
if (Serial.available() > 0) {
  ByteIn=Serial.read(); // Leemos lo que transmitiremos desde Java
  if (ByteIn == '1'){
   digitalWrite(led, HIGH);
   delay(7000);
   digitalWrite(led, LOW);
  } else {
   digitalWrite(led, LOW);
  }
}
}

total ya despues de toda esa biblia (gracias por leerla, por cierto)
en ocaciones aleatorias se interrumpe o satura el puerto y sale error: Java (TM) Platform Binary SE
y ese es el mismo error que me sale si desconecto el arduino o intento abrir el monitor serial en el IDE de arduino con el programa corriendo

Primero que no es buena idea poner 7segundos de espera. Delay congela practicamente el micro en un bucle infinito que no escucha nada desde los puertos.
Usa la libreria Timer para apagar el led al tiempo deseado o con interrupciones de reloj.

Despues de leer lo que querias deberias limpiar el buffer para que no siga leyendo mas hasta procesar.

maxid:
Primero que no es buena idea poner 7segundos de espera. Delay congela practicamente el micro en un bucle infinito que no escucha nada desde los puertos.
Usa la libreria Timer para apagar el led al tiempo deseado o con interrupciones de reloj.

Despues de leer lo que querias deberias limpiar el buffer para que no siga leyendo mas hasta procesar.

hola.
pero entonces que uso en vez de Delay? porque el objetivo de ese delay es que active el Relay 7 segundos (la duracion del timbre) porque sino durara eternamente jajaja...
y como limpio el buffer?
disculpa tanta duda pero soy estudiante de preparatoria, no tengo ningun titulo de nada :frowning:

gabrielpazc:
hola.
pero entonces que uso en vez de Delay? porque el objetivo de ese delay es que active el Relay 7 segundos (la duracion del timbre) porque sino durara eternamente jajaja...
y como limpio el buffer?
disculpa tanta duda pero soy estudiante de preparatoria, no tengo ningun titulo de nada :frowning:

Hola Gabriel.

En vez del Delay puedes usar la función millis() de Arduino. Esta función te da el tiempo que lleva encendida tu placa, esto lo puedes usar a tu favor y sumarle el tiempo que quieres de espera. Te adjunto un código donde lo podrás entender mejor.

 /*EducaChip - Uso de la función millis para sustituir delay*/
      /*                    www.educachip.com                    */
      
 
//Se declara una variable que almacenará el tiempo actual (real) transcurrido
//desde que se enciende la placa.
unsigned long tiempo = 0;
 
//Se declara una variable que almacenará el último valor de tiempo en el que se
//ejecutó la instrucción (delay).
unsigned long t_actualizado = 0;
 
//Se declara una variable que almacenará el tiempo que se desea que dure el delay.
unsigned long t_delay = 20;
 
void setup(){
 
  /*
  Se configura el setup
  */
}
 
void loop() {
 
  //Se almacena el tiempo que ha transcurrido desde que se encendió el Arduino.
  tiempo = millis();
  
  //Si ese tiempo es mayor que el intervalo de deseado (equivalente al tiempo
  //de delay) se actualiza el intervalo y se ejecutan las instruciones relacionadas.
  //La idea detrás de este algoritmo consiste en pensar que si han transcurrido
  //20ms y se desea un delay de 30ms cada vez, cuando se superen esos 30ms la
  //variable con la que se compara pasa a ser 60ms. Una vez se alcanzan los 60ms
  //pasa a ser 90ms y así sucesivamente.
  if( tiempo > t_actualizado + t_delay) {
  
    //Se actualiza el tiempo que ha de transcurrir para el próximo delay.
    t_actualizado = tiempo;
    
    /*
    Se define el conjunto de instruciones que se desea que se realicen cada vez
    que transcurra el tiempo establecido anteriormente (mover un motor, cambiar
    de estado un LED, enviar datos...).
    */
  }
 
  /*
  Se ejecutan el resto de instrucciones del programa.
  */
 
}

Te dejo un link de un articulo para que leas acerca de los inconvenientes que puede causar la función Delay. "http://www.educachip.com/razones-no-usar-funcion-delay-en-arduino/"

Saludos.

gabrielpazc:
hola.
pero entonces que uso en vez de Delay? porque el objetivo de ese delay es que active el Relay 7 segundos (la duracion del timbre) porque sino durara eternamente jajaja...
y como limpio el buffer?
disculpa tanta duda pero soy estudiante de preparatoria, no tengo ningun titulo de nada :frowning:

Si lees, te deje el link a la libreria donde explica como usarla.
3 lineas y desactivas el rele al tiempo que quieras.

maxid:
Si lees, te deje el link a la libreria donde explica como usarla.
3 lineas y desactivas el rele al tiempo que quieras.

me puedes ayudar con el timer, es que no puedo comprender la libreria :confused: llevo esto :frowning:

const int led = 13;
int ByteIn = 0;
#include "Timer.h"
Timer t;
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(led, OUTPUT);
  digitalWrite(led, LOW);
  

}

void loop() {
  // put your main code here, to run repeatedly:
  
if (Serial.available() > 0) {
  ByteIn=Serial.read(); // Leemos lo que transmitiremos desde Java
  if (ByteIn == '1'){
  t.pulse(led, 7000, HIGH); // 7 seg

  
    t.update(); 
  ByteIn=0;
 digitalWrite(led, LOW);
 
  } else {
   digitalWrite(led, LOW);
  }

}

}

te ayudo como bloques tu lo arreglas con tu codigo

Timer T; //creamos el objeto

//Rutina de apagado
void DesactivarRele()
{ 
  digitalWrite(led,LOW); 
}


void loop()
{
  

  t.update(); //esto es lo que actualiza los tiempos, lo pones al principio del loop

  if (Serial.available() > 0) 
  {
    ByteIn=Serial.read(); // Leemos lo que transmitiremos desde Java
    if (ByteIn == '1')
    {
       digitalWrite(led, HIGH); // lo activo manualmente
       T.after(7000, DesactivarRele); //activo el evento que despues de transcurrido el tiempo lo desactivamos
...
resto de tu programa



}//fin del loop

con esta libreria puedes hacer que parpadee un led, disparar eventos por tiempos y mucho mas. no es preciso qye que depende del tiempo de ejecucion de otras intrucciones, pero sirve para estos fines.

maxid:
te ayudo como bloques tu lo arreglas con tu codigo

Timer T; //creamos el objeto

//Rutina de apagado
void DesactivarRele()
{
  digitalWrite(led,LOW);
}

void loop()
{

t.update(); //esto es lo que actualiza los tiempos, lo pones al principio del loop

if (Serial.available() > 0)
  {
    ByteIn=Serial.read(); // Leemos lo que transmitiremos desde Java
    if (ByteIn == '1')
    {
      digitalWrite(led, HIGH); // lo activo manualmente
      T.after(7000, DesactivarRele); //activo el evento que despues de transcurrido el tiempo lo desactivamos
...
resto de tu programa

}//fin del loop





con esta libreria puedes hacer que parpadee un led, disparar eventos por tiempos y mucho mas. no es preciso qye que depende del tiempo de ejecucion de otras intrucciones, pero sirve para estos fines.

maxid:
te ayudo como bloques tu lo arreglas con tu codigo

Timer T; //creamos el objeto

//Rutina de apagado
void DesactivarRele()
{
  digitalWrite(led,LOW);
}

void loop()
{

t.update(); //esto es lo que actualiza los tiempos, lo pones al principio del loop

if (Serial.available() > 0)
  {
    ByteIn=Serial.read(); // Leemos lo que transmitiremos desde Java
    if (ByteIn == '1')
    {
      digitalWrite(led, HIGH); // lo activo manualmente
      T.after(7000, DesactivarRele); //activo el evento que despues de transcurrido el tiempo lo desactivamos
...
resto de tu programa

}//fin del loop





con esta libreria puedes hacer que parpadee un led, disparar eventos por tiempos y mucho mas. no es preciso qye que depende del tiempo de ejecucion de otras intrucciones, pero sirve para estos fines.

muchas gracias :smiley: con tu ayuda ya pude :slight_smile:

ahora queda que acomodes tu codigo.
para limpiar el buffer de comunicaciones es Serial.flush(); si quedó algun caracter esperando lo borra, sobre todo si del lado del pc viene un CR/LR y eso hace que entre de nuevo a consultar.

maxid:
ahora queda que acomodes tu codigo.
para limpiar el buffer de comunicaciones es Serial.flush(); si quedó algun caracter esperando lo borra, sobre todo si del lado del pc viene un CR/LR y eso hace que entre de nuevo a consultar.

si acabo de poner eso del Serial.flush(); porque aun sustituyendo el delay fallo, tambien puse un output.flush(); en java despues de enviar datos... por cierto tengo un thread.sleep(1000); en java cuando entra en la condicion:

 String yolo = formato.format(hoy);
       
           if(yolo.equals("06:55:00 AM") || yolo.equals("07:00:00 AM") || yolo.equals("07:50:00 AM") || yolo.equals("08:40:00 AM") || yolo.equals("09:25:00 AM") || yolo.equals("10:00:00 AM") || yolo.equals("10:05:00 AM") || yolo.equals("10:50:00 AM") || yolo.equals("11:40:00 AM") || yolo.equals("12:30:00 PM") || yolo.equals("12:40:00 PM") || yolo.equals("01:30:00 PM") || yolo.equals("02:20:00 PM")) {
Thread.sleep(1000);          
 enviarDatos(Turn_LED_On);
        
        }

para que solo envie una vez los datos porque me di cuenta que en ese segundo mandaba muchas veces la informacion por que el procesador cumplia la condicion del if muchas veces en en ese segundo del hilo... crees que tambien deba quitarlo y buscar una otra manera de que solo lo envie una vez o aqui no afecta el "retraso"?

Volvamos del principio.
Cuantos timbre deseas controla?
1? Olvidate de arduino. Usa unn rele commandado x el Serial

maxid:
Volvamos del principio.
Cuantos timbre deseas controla?
1? Olvidate de arduino. Usa unn rele commandado x el Serial

¿Como que me olvide de arduino, lo quito o te refieres a que en el codigo de arduino ya esta solucionado?
son 13 timbres al dia...

gabrielpazc:
¿Como que me olvide de arduino, lo quito o te refieres a que en el codigo de arduino ya esta solucionado?
son 13 timbres al dia...

13 aparatos timbres? o 13 timbrazos? porque si es para hacer sonar "El" timbre con este circuito y una pc lo haces.

Ahora si lo que quieres es tenerlos programados sin el uso de una PC, si usa arduino junto a un reloj ds1307. y lo reprogramas o corrijes la hora con una PC

seriatorelay.png