Problemas con funcion millis () . Conflicto

Amigo noter, efectivamente para enviar informacion del arduino a la app utilizo un serial.printl.

Lo que no entiendo es que afecta que dentro del if si la app recibe el dato y fuera no. sera por el serial, sera por:

Serial.available

No estoy seguro. He realizado varias pruebas y no doy con la falla.

Probe tu ejemplo quitando ese digital.write y funciono de maravilla.

Gracias

Bueno. Como te habrás dado cuenta, al sacar los println fuera de los if se van a imprimir los tres consecutivamente. No entiendo muy bien qué quieres hacer con ello, pero me da que igual el problema esté en el programa que recibe o en el propio emisor bluetooth. Tal vez que al existir más datos que los que espere el programa no los estés procesando bien o que el dispositivo bluetooth requiera de alguna pausa entre líneas. ¿Has probado a poner un delay entre los println?

Sí la verdad es bastante raro. Probaré utilizando un delay al ver si así soluciono. Porque el problema de dejarlo adentro tendría que hacer unos arreglos con Flag para que cuando la corriente sea cero envíe esa información adicional la App.

¿Pero cuál es el problema actualmente y por qué hay que sacar los println del if? ¿cuándo y cómo deberían enviarse esos datos a la aplicación? Es que no entiendo qué me quieres decir con lo de los arreglos con flag.

Recuerdas esto? Lo que colocamos al final con tu idea de enviar un dato cuando la corriente sea igual a cero y así sabemos que esta apagado el releenchufe

: [Select]

//////////////////////////////////////////////////////////////////////////////////
///////////////////////////////PEQUEÑA CLASE PARA CONTROL AHORRO//////////////////
///////////////////////////////////////////////////////////////////////////////////
// uso: 
// Crear un dispositivo: Relenchufe enchufe(pin analógico, pin relé);
// Controlar el dispositivo (devuelve la corriente actual): enchufe.chequea();
// Obtener lectura de referencia: enchufe.getMaxCurrent();
// Armar un enchufe apagado: enchufe.arma();

const unsigned TIEMPODESCONEXION=5000; // TIEMPO TRAS EL QUE SE DESCONECTARÁ EL ENCHUFE SI PERMANECE BAJO

class Relenchufe{
public:
      // constructor
      Relenchufe(int pinAnalog, int pinLed): 
      pinLectura(pinAnalog), led(pinLed), current1(0), millisInicioApagado(0){
            pinMode(pinLectura, INPUT);
            pinMode(led, OUTPUT);
            digitalWrite(led, HIGH);
      };

      int getMaxCurrent(){
            return(current1);
      };
      
      void arma(void){
            digitalWrite(led, HIGH);
      }
      
      int chequea(void){
            int sensorMax = 0;
            int sensorValue = 0;
            for(int cont=0;cont<450;cont++)
            {
                  sensorValue =  analogRead(pinLectura);
                  if (sensorValue > sensorMax) 
                  {  
                        sensorMax = sensorValue;
                  }
            }
            current=(float)sensorMax/1024*5/800*2000000; //Voltaje del sensor 5V. Recuerda que se puede simplificar la fórmula
            if (current < current1*0.4)
            {     
                  if (millisInicioApagado > 0) 
                  {                 
                        if ((millis() - millisInicioApagado) >= TIEMPODESCONEXION)
                        {
                              current1 = current = 0; // PREGUNTA: ¿Una vez apagado se supone que las lecturas posteriores van a ser cero? Si no es así, habrá que cambiar estrategia.
                              digitalWrite(led, LOW);         
                              millisInicioApagado = 0;   // y reseteamos el valor de consumo y el temporizador
                        }
                  } 
                  else 
                  {
                        millisInicioApagado=millis();          // Iniciamos temporizado
                  }
            } 
            else 
            {
                  millisInicioApagado=0;     // Desactivamos la posible cuenta atrás
                  current1 = current ;
                  digitalWrite(led, HIGH);
            }
            return(current);
      }

private:
      int pinLectura;     // Pin analógico para leer corriente
      int led;        // Pin relé de enchufe
      int current;    // Valor de la última lectura (máxima del for)
      int current1;       // Valor "alto" de consumo. Se irá estableciendo dinámicamente. Cuando baje del 60% iniciará el temporizador de desconexión
      // milisegundo en el que inicia la bajada de consumo e inicia el temporizado para desconexión. Mayor que cero, significa que se ha iniciado la cuenta.
      unsigned millisInicioApagado;
};

///////////////////////////////////////// hasta aquí la clase que seria metida en una libreria ///////////////////////////////////////////////////     


                                 //Variable de tipo cadena para guardar los datos recibidos
 
String dato; 
int led1= 7;
int led2= 8;
Relenchufe enchufe1(A0, 7); //A0 entrada analoga, 8 pin de salida, 1 dato a enviar 
Relenchufe enchufe2(A1, 8);


void setup() 
{
      Serial.begin(9600);
	  pinMode(led1, OUTPUT); 
	  pinMode(led2, OUTPUT); 
          digitalWrite(7,LOW);
	  digitalWrite(8,LOW);
	  
}


void loop() 
{ 
  while (Serial.available()) { 
    delay(10);
     if (Serial.available() > 0) {
      char c = Serial.read();                //Cuando se recibe un dato, se guarda como carácter
      dato += c;                             //Cadena de caracteres formada por la suma de los datos recibidos 
     }
  } 
  
  if (dato.length() > 0) {       //Comprueba que la variable "dato" tenga al menos un caracter 
    
    if(dato == "1") {                 //Recibimos dato y comparamos
      enchufe1.arma();       //Enciende el led 
    }
    if(dato == "2") { 
      enchufe2.arma();
    }
     dato="";  //Declaramos la variable "vacía" para volver a guardar de nuevo caracteres y compararlos con cada uno de los casos
  }
  int corriente_actual=enchufe1.chequea();
  Serial.print("Corriente actual Sensor 1: ");
  Serial.println(corriente_actual);
  if(corriente_actual==0) Serial.println("1"); // enchufe1 apagado
  delay (2000); 
  corriente_actual=enchufe2.chequea();
  Serial.print("Corriente actual Sensor 2: ");
  Serial.println(corriente_actual);
  if(corriente_actual==0) Serial.println("2"); // enchufe2 apagado
  delay (2000);  
}

Bueno aquí ese sería. Printl después de la comparación de corriente actual igual a cero no estas haciendo nada porque ese dato no lo está recibiendo la App.

Por eso digo que no lo puedo sacar del if de recibir dato para sí poder enviarlo.

Y lo necesito afuera cómo en el ejemplo que tu mismo armaste.

Graciaz

Tal vez el problema sea que estamos utilizando serial tanto para la depuración como para enviar los datos a la aplicación.
Si en lugar de

  int corriente_actual=enchufe1.chequea();
  Serial.print("Corriente actual Sensor 1: ");
  Serial.println(corriente_actual);
  if(corriente_actual==0) Serial.println("1"); // enchufe1 apagado
  delay (2000); 
  corriente_actual=enchufe2.chequea();
  Serial.print("Corriente actual Sensor 2: ");
  Serial.println(corriente_actual);
  if(corriente_actual==0) Serial.println("2"); // enchufe2 apagado
  delay (2000);

lo dejamos en

  int corriente_actual=enchufe1.chequea();
  if(corriente_actual==0) Serial.println("1"); // enchufe1 apagado
  delay (2000); 
  corriente_actual=enchufe2.chequea();
  if(corriente_actual==0) Serial.println("2"); // enchufe2 apagado
  delay (2000);

¿cambia en algo el resultado?

Hola noter, dame 10 min y pruebo ahora mismo.

Tambien probare con una recomendacion que me dio jose, puedes verla en el otro post.

Ya te indico los resultados.

Noter efectivamente ahi estaba el problema.

Tu conclusion la saque yo ayer tambien, pero en ves de eliminar el serial.printl para imprimir el valor del sensor, y solo dejarlo para enviar un dato a la app, probe haciendolo activando dos puertos seriales, uno para el envio y otro para imprimir los valores.

Claro a cuestion de pruebas y verificacion del funcionamiento ahorita, debo visualizar el valor de la corriente mientras se hacen las pruebas respectivas. Luego esos serial.printl efectivamente pueden ser eliminados para que asi no me den conflicto al enviar los datos a la aplicacion.

Armare ahorita mismo la otra clase del USB, para que le heches un ojo porfavor y luego ver como metemos eso en una libreria. Y practicamente el proyecto estaria listo.

Sin palabras para agradecer todo tu apoyo noter. Gracias a tus conocimientos y recomendaciones he podido avanzar con grandes pasos y he aprendido muchas cosas que no sabia.

Agradecido.

Bien noter, esta seria la clase.

Vamos a ver si entendi perfectamente la tuya jajaja esta es la prueba. Si la entendi bien esta deberia estar bien entonces.

/////////////////////////////////////////////////////////////////////////////////
///////////////////////////////PEQUEÑA CLASE PARA CONTROL AHORRO//////////////////
///////////////////////////////////////////////////////////////////////////////////
// uso: 
// Activar un puerto USB por un tiempo determinado luego de recibir un dato desde
// la aplicacion en Android para la carga de celulares.

const unsigned TIEMPODESCONEXION= 14400000; // TIEMPO QUE ESTARA ACTIVO EL PUERTO USB 4 HORAS

class USB{
public:
      // constructor
      USB(int pinUsb): 
      rele(pinRele), millisInicioApagado(0){
            pinMode(rele, OUTPUT);
            digitalWrite(rele, LOW);
      };

      
	  int cargando(void){
            digitalWrite(rele, HIGH);  // Encendemos el USB al recibir un dato de la aplicacion   
			if (rele == HIGH)
				{
				if (millisInicioApagado > 0) 
                  {                 
                        if ((millis() - millisInicioApagado) >= TIEMPODESCONEXION)
                        {
                              digitalWrite(rele, LOW);     // Apagamos el USB    
                              millisInicioApagado = 0;   // y reseteamos el temporizador
                        }
                  } 
				else 
                  {
                        millisInicioApagado=millis();          // Iniciamos temporizado
                  }
				 }
            } 
            else 
            {
                  millisInicioApagado=0;     // Desactivamos la posible cuenta atrás
				  digitalWrite(rele, LOW) ;   // Mantenemos el USB apagado
            }
           
      }

private:
      int rele;     // Pin salida para activar o desactivar el USB con un rele
      
};

///////////////////////////////////////// hasta aquí la clase que seria metida en una libreria ///////////////////////////////////////////////////

Que opinas de ella ?

Gracias

Bueno. Ahora mismo no tengo mucho tiempo, pues tengo que salir. A la noche lo revisamos de nuevo.
De momento sólo puedo decirte que creo que tienes llaves desequilibradas, y que el
digitalWrite(rele, HIGH); // Encendemos el USB al recibir un dato de la aplicacion
al principio de la función desvirtúa el if/else posteriores, pues necesariamente rele va a ser HIGH siempre. Supongo que ese digitalWrite se debe escribir una vez al recibir el comando, y la función cargando tal como está se ocuparía de la revisión del timer. Lo lógico tal vez es que hagas una función start que haga el digitalWrite y luego la función cargando ya iniciará timer cuando detecte ese high en su primera pasada.
Saludos y hasta luego.

Ten en cuenta que es bastante más sencillo que la otra clase, que necesitaba rearmar el temporizador dependiendo de las lecturas:

/////////////////////////////////////////////////////////////////////////////////
///////////////////////////////PEQUEÑA CLASE PARA CONTROL AHORRO//////////////////
///////////////////////////////////////////////////////////////////////////////////
// uso: 
// Activar un puerto USB por un tiempo determinado luego de recibir un dato desde
// la aplicacion en Android para la carga de celulares.
// usb.start(); inicia el temporizador.
// cargando(); revisa el temporizador.

const unsigned long TIEMPODESCONEXION= 14400000; // TIEMPO QUE ESTARA ACTIVO EL PUERTO USB 4 HORAS. Aquí sí hay que utilizar long, porque medimos más de 65535 ms

class USB{
public:
      // constructor
      USB(int pinRele): 
      rele(pinRele){
            pinMode(rele, OUTPUT);
            digitalWrite(rele, LOW);
      };

      void start(void){
            digitalWrite(rele, HIGH);  // Encendemos el USB al recibir un dato de la aplicacion   
            millisInicioApagado=millis();          // Iniciamos temporizado
      }


      void cargando(void){
            if (digitalRead(rele)==HIGH) // Si el relé está activado revisamos el temporizador
            {                 
                  if ((millis() - millisInicioApagado) >= TIEMPODESCONEXION)
                  {
                        digitalWrite(rele, LOW);     // Apagamos el USB    
                  }
            } 
      }

private:
      int rele;     // Pin salida para activar o desactivar el USB con un rele
      unsigned long millisInicioApagado;
};

Me equivoque en unas cosas pequeñas jajajaaj. Gracias por las correcciones.

Ok, ahora para poder utilizarlo en el archivo principal, quedaria mas o menos asi no?, tengo una duda en ok, cuando reciba un dato llamo a la funcion start que me activa el rele. Pero donde debo llamar a la funcion cargando para que verifique si ya el tiempo paso ? . o el automaticamente al llamar a la primera funcion de start el correra todos los loop de esa clase? .

ejemplo

String dato; 
int rele=9;
Relenchufe enchufe1(A0, 7); //A0 entrada analoga, 8 pin de salida, 1 dato a enviar 
Relenchufe enchufe2(A1, 8);
USB rele1(9)


void setup() 
{
      Serial.begin(9600);
      pinMode(led1, OUTPUT); 
      pinMode(led2, OUTPUT); 
      digitalWrite(7,LOW);
      digitalWrite(8,LOW);
	  
}


void loop() 
{ 
  while (Serial.available()) { 
    delay(10);
     if (Serial.available() > 0) {
      char c = Serial.read();                //Cuando se recibe un dato, se guarda como carácter
      dato += c;                             //Cadena de caracteres formada por la suma de los datos recibidos 
     }
  } 
  
  if (dato.length() > 0) {       //Comprueba que la variable "dato" tenga al menos un caracter 
    
    if(dato == "1") {                 //Recibimos dato y comparamos
      enchufe1.arma();       //Enciende el led 
    }
    if(dato == "2") { 
      enchufe2.arma();
    } 
	if(dato == "3") {
	  rele1.start
	}
    dato="";  //Declaramos la variable "vacía" para volver a guardar de nuevo caracteres y compararlos con cada uno de los casos
  }
  int corriente_actual=enchufe1.chequea();
  if(corriente_actual < 0) Serial.println("1");
  delay (1000);
   
}

Ahora solo quedaria pasar las dos clases a una libreria para que no este todo ese mezclote junto

Hola.
Por ahí donde tienes el
int corriente_actual=enchufe1.chequea();

supongo que deberías poner lo mismo para enchufe2 (además de hacer tus sumas de consumos y demás), y también debes poner el rele1.cargando() para que revise en cada loop.
Bueno. Primero veamos si obtenemos un funcionamiento razonable, y luego pasamos las clases a una librería (que además podría incluir alguna funcionalidad más, como controlar una colección de esas clases sin tener que liarte desde el loop).

ok perfecto noter. mañana hare la prueba solo de esa nueva clase para los usb, una ves funcione perfectamente , hare la prueba con las dos clases que funcionen juntos. y si todo marcha excelente, pues pasamos eso a una libreria.

Gracias.

Buenas noches noter, te adjunto el codigo que probe para los usb y funciona de maravilla.

Excelente. Ahora si deseo probar las dos clases juntas como hago?, simplemente pongo una debajo de la otra y listo ?..

O mejor las metemos en una libreria de una ves para probarlas.

/////////////////////////////////////////////////////////////////////////////////
///////////////////////////////PEQUEÑA CLASE PARA CONTROL AHORRO//////////////////
///////////////////////////////////////////////////////////////////////////////////
// uso: 
// Activar un puerto USB por un tiempo determinado luego de recibir un dato desde
// la aplicacion en Android para la carga de celulares.
// usb.start(); inicia el temporizador.
// cargando(); revisa el temporizador.

const unsigned long TIEMPODESCONEXION= 10000; //14400000 TIEMPO QUE ESTARA ACTIVO EL PUERTO USB 4 HORAS. Aquí sí hay que utilizar long, porque medimos más de 65535 ms

class USB{
public:
      // constructor
      USB(int pinRele): 
      rele(pinRele){
            pinMode(rele, OUTPUT);
            digitalWrite(rele, LOW);
      };

      void start(void){
            digitalWrite(rele, HIGH);  // Encendemos el USB al recibir un dato de la aplicacion   
            millisInicioApagado=millis();          // Iniciamos temporizado
      }


      void cargando(void){
           if (digitalRead(rele)==HIGH) // Si el relé está activado revisamos el temporizador
            {                 
                  if ((millis() - millisInicioApagado) >= TIEMPODESCONEXION)
                  {
                        digitalWrite(rele, LOW);     // Apagamos el USB    
                  }
            }
           else
          {
          digitalWrite(rele, LOW);
          millisInicioApagado=0 ;
          } 
      }

private:
      int rele;     // Pin salida para activar o desactivar el USB con un rele
      unsigned long millisInicioApagado;
};

String dato; 
USB rele1(7) ;
USB rele2(8) ;


void setup() 
{
      Serial.begin(9600); 
      digitalWrite(7,LOW);
      digitalWrite(8,LOW);
	  
}


void loop() 
{ 
  while (Serial.available()) { 
    delay(10);
     if (Serial.available() > 0) {
      char c = Serial.read();                //Cuando se recibe un dato, se guarda como carácter
      dato += c;                             //Cadena de caracteres formada por la suma de los datos recibidos 
     }
  } 
  
  if (dato.length() > 0) {       //Comprueba que la variable "dato" tenga al menos un caracter 
    
    if(dato == "1") {                 //Recibimos dato y comparamos
      rele1.start();       //Enciende el led 
    }
    
    if(dato == "2") {                 //Recibimos dato y comparamos
      rele2.start();       //Enciende el led 
    }
    dato="";  //Declaramos la variable "vacía" para volver a guardar de nuevo caracteres y compararlos con cada uno de los casos
  }
  
  rele1.cargando() ;
  rele2.cargando() ;
   
}

Perfecto. Puedes poner ambas clases al principio de tu código o, bien, crea una nueva pestaña en tu proyecto, le das un nombre con extensión .h y pones el código de las dos clases en ella. En el sketch pones un
#include "nombre.h" (con comillas, porque no está en la carpeta de librerías, sino en la misma del sketch).
Con cualquiera de los dos sistemas podrías utilizar ambas clases ya, si quieres ir probando.
Podrías incluso, poniendo el nombre.h en una carpeta con el mismo nombre dentro de libraries, utilizarlo como una librería normal (#include <nombre.h>) pero es preferible estandarizarlo un poco (ponerle los #ifndef para evitar la reinclusión, y separar el código de las definiciones y pasarlo a un archivo.cpp). Esto requiere poquito tiempo, pero dame un día y de paso puedo ampliar la librería y hacer una clase que englobe y gestione las otras.

Bien noter excelente. todo funciona de maravilla por separado jajajajja las dos clases.

Ojala al unirlas y llamarlas paralelamente no den errores o fallas como por ejemplo el que la comunicación con el modulo bluetooth por los serial.printl

Tengo una cantidad enorme de archivos y pruebas en la pc. estoy limpiandolos, para quedarme con los dos finales, y adjuntartelos aqui, para pasarlos a la libreria.

Dame unos min y con gusto te los monto.

Gracias noter, por dedicar tu tiempo en ayudarme y ser mi maestro de android jajajaj. Porque me has enseñado una cantidad incontable de cosas.

Hola.
Pues aquí tienes las clases que habíamos creado transformadas a librería. Con meter los tres archivos en una carpeta que se llame enchufes el sketch de ejemplo que he puesto debería funcionarte, ya que la librería quedaría en la propia carpeta del proyecto y te aparecerán sus archivos en pestañas (el sketch es lo único que deberías ajustar a tu programa). Si quisieras instalar la librería en el ide, aunque dudo que le vayas a dar otros usos posteriores, tan solo tendrías que poner los archivos .cpp y .h en una carpeta con el mismo nombre que los archivos (arduino\libraries\pwrSvr).
Si observas el fichero .h verás que contiene sólo las definiciones de las clases. De esta forma, echando un vistazo a dicho archivo te puedes hacer una idea esquemática de lo que hace (habría que comentarla mejor, lo sé )). El código propiamente dicho se encuentra en el archivo.cpp.
Prueba y cuenta.
Por cierto, ¿Qué arduino estás utilizando? Porque si es alguno de los que tienen varios serial, podrías utilizar uno aparte para el bt y evitar problemas con la consola.

pwrSvr.h (1.22 KB)

enchufes.ino (1.45 KB)

pwrSvr.cpp (2.47 KB)

Excelente amigo noter.

Lo revisare con calma a ver como va todo.

Efectivamente estoy usando el arduino mega que posee 3 puertos seriales de comunicacion.

Hice la prueba habilitando dos para ver si resolvia el problema de la consola y no me funciono.

De igual amanera como te dije realmente no necesito la consola del monitor para el resultado final.

Muchas gracias. Te estare comentando.

Buenas noches amigo Noter.

He realizado un par de pruebas y todo funciona de maravilla. Excelente esas clases implementadas en una libreria.

Ahora recuerdas una comparación que deseo hacer una ves obtenido el valor de los 5 sensores sumarlos todos.

de esta manera podría hacerlo ? .

if (enchufe1.chequea+enchufe2.chequea+enchufe3.chequea < o > que X numero)
     Accion a tomar?

Gracias .