Problemas con funcion millis () . Conflicto

Amigo Noter realice unas cuantas pruebas con el ultimo código que puse y funciona de maravilla. Cero errores y fallas.

Pero lo proble como void loop principal, no como clase.

No deberia dar problemas como clase supongo

A la espera de tus comentarios al respecto.

Hola de nuevo, kenny0414.
Veo que hoy has estado muy activo :slight_smile: me está costando seguirte. Te suelto algunas ideas "desordenadas", basadas sobre todo en tu último código-loop. Sería preferible que publicaras el código entero, porque hay algunas cosas que no veo aunque supongo que tienes controladas:

  • ¿La medición para hallar la lectura al final la vas a hacer con millis o contando 400 mediciones?
  • ¿El máximo de referencia (sobre el que calculas el 40%) se actualizará siempre al alza?, es decir ¿siempre que la nueva lectura lo supere es el que va a quedar indefinidamente mientras no haya otra mayor?
  • La función map sirve perfectamente para obtener el porcentaje. map (ultimaLectura, 0, maxValue, 0, 100) transforma el valor ultimaLectura de una escala que va de cero a maxValue (el valor con el que queremos comparar, que sería el 100%) y una escala que va de cero a 100. Supongo que al ser una función "nativa" de arduino esté bastante optimizada y tal vez sea más rápido que multiplicar por 0.4 y comparar; pero ambas opciones son válidas.
  • A efectos de comparar porcentajes, me es lo mismo comparar lecturas analógicas que las corrientes equivalentes a esas lecturas analógicas, así que para ese cálculo considero más rápido y sencillo comparar el valor bruto.
  • Lo que no quita que a la hora de mostrar el dato en pantalla podamos convertirlo a corriente. A tal efecto, creo que puedes simplificar tu fórmula:
    current=(float)sensor_max/10245/8002000000;
    haz el cálculo para 1: 1/10245/8002000000=12.2070313 (si no me equivoco), y sustituímos
    current=(float)sensor_max*12.2070313
  • Creo que andamos rondando más o menos por el mismo camino. Cuando puedas pon tu código completo, lo analizamos y si quieres lo convemos en clase.

Hola noter Buenas noches (en mi pais)

Codigo probado varias y veces y funcionando perfectamente.

#define ELECTRICITY_SENSOR A0 // Analog input pin that sensor is attached to

unsigned long current; //amplitude current
int led= 8; 
int current1;
long millisInicioApagado = 0;
const unsigned long TIEMPODESCONEXION=5000;

void setup() 
{
  Serial.begin(9600); 
  digitalWrite(led,HIGH);
  pinMode(ELECTRICITY_SENSOR, INPUT);
  pinMode(led, OUTPUT);
}

void loop() 
{
int sensorMax = 0;
int sensorValue = 0;
for(int cont=0;cont<450;cont++)
      {
    sensorValue =  analogRead(ELECTRICITY_SENSOR);
      if (sensorValue > sensorMax) 
          {  
          sensorMax = sensorValue;
          }
      }
    delay(500);
  
  int sensor_max;
  sensor_max = sensorMax ;
  current=(float)sensor_max/1024*5/800*2000000; //Voltaje del sensor 5V
  
  Serial.println("The amplitude of the current is(in mA)");
  Serial.println(current);
  
   if (current > 0)
   {
   digitalWrite(led, HIGH);
   }
   if (current < current1*0.4)
      {     
          if (millisInicioApagado > 0) 
          {                 
            if ((millis() - millisInicioApagado) >= TIEMPODESCONEXION)
              {
               if (current <= current1*0.4 )
                { 
                  current1 = current;
                  Serial.println("Termino Temporizador");
                  digitalWrite(led, LOW);         
                  millisInicioApagado = 0;   // y reseteamos el valor de consumo y el temporizador
                }   
              }
           } 
           else 
              {
               millisInicioApagado=millis();          // Iniciamos temporizado
               Serial.println("Comenzo temporizador");
              }
        } 
   else 
   {
    millisInicioApagado=0;     // Desactivamos la posible cuenta atrás
    current1 = current ;
   }

}

Respondiendo a tus puntos.

1-Contando las 400 mediciones , en el codigo podemos observarlo.

2-La variable current1 a la cual le saco el 40% debe ser siempre fija , es decir que el mismo valor que utilizo para comparar la primera ves, sea el mismo para comparar la segunda vez luego del tiempo de espera. Pasar un valor de alza no me importa, porque ya inmediatamente el se saldria del tiempo de espera.

3-Ok perfecto, seria cuestion de probar entonces con el map, pero si con ambas funciona solo que la diferencia es tener una comparacion mas rapido, no es un problema.

4-No me gustaria comparar el valor bruto, solo cuestion de gustos jajajaja.

5-Respecto a la formula si tenia pensado simplificarla solo que no lo habia hecho porque por ahi ajusto la precision, lo haria de ultimo. Gracias por la recomendacion.

Pues asi es amigo Noter, y la verdad no tengo palabras para agradecerle todo su apoyo en mi proyecto.

Ahora luego que revises toda la programacion.

Podemos pasarlo a clase creando los 5 enchufes y agregarle la funcion del millis para el muestreo de los 5 sensores de manera consecutiva , con o sin el for, de la manera que sea mas fiable y garantice el correcto funcionamiento.

Saludos
Estaba revisando el primer codigo publicado y vi algo que no se si lo han notado pues no lei todas las repuestas:

previousMillis esta definida en una funcion fuera de loop() y luego es usada en loop(), lo que puede causar problemas porque no es global, y solo funcionara bien en donde se declaro es decir en int getMaxValue().

Como no poseo el sensor solo puedo revisar el codigo y no ver como funciona.

Hola max, efectivamente ya eso fue corregido.

Gracias por el aporte ! Si deseas actualizarte lee solo la pag 3 . Estan las ultimas correcciones.

Hola.
Si, como dices, funciona perfectamente, ¡adelante con los faroles!
Como parece que te has percatado, una clase es un paquete con sus variables y sus funciones. Todo tu programa se puede empaquetar en una clase y cada objeto de esa clase tendrá todas esas variables y funciones independientes. Como ves, el código de la clase es prácticamente el mismo que tienes en tu programa, sólo que estructurado, así que no me llevará mucho tiempo hacer la clase.
En un ratillo te pongo el código, con alguna pequeña modificación (te las explico en los comentarios sencillamente para que veas cosillas, pero si quieres volver a dejarlo como lo tenías, no te será difícil).

Bueno.
Te pongo el código. Como te dije he modificado pequeñas cosas y te las he comentado. Mira a ver si funciona, y si es así podemos intentar construir tu código para tus cinco sensores, que debería ser bastante sencillo de implementar.

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

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 getCurrent(){
            return(current);
      };

      int getMaxCurrent(){
            return(current1);
      };
      

      void chequea(void){
            int sensorMax = 0;
            int sensorValue = 0;
            for(int cont=0;cont<450;cont++)
            {
                  sensorValue =  analogRead(pinLectura);
                  if (sensorValue > sensorMax) 
                  {  
                        sensorMax = sensorValue;
                  }
            }
            //delay(500); ¿Este delay no tiene ninguna funcionalidad, no? 
            
            // No entiendo por qué utilizas la variable intermedia sensor_max lo he sustituido con la línea siguiente
//            int sensor_max;
//            sensor_max = sensorMax ;
//            current=(float)sensor_max/1024*5/800*2000000; //Voltaje del sensor 5V
            current=(float)sensorMax/1024*5/800*2000000; //Voltaje del sensor 5V. Recuerda que se puede simplificar la fórmula
            
            // Este if no parece tener mucho sentido, pues se evalúa todas las veces. Creo que si metemos el digitalWrite en el else del if 40%,
            // debería tener similar funcionamiento. 
//            if (current > 0)
//            {
//                  digitalWrite(led, HIGH);
//            }
            if (current < current1*0.4)
            {     
                  if (millisInicioApagado > 0) 
                  {                 
                        if ((millis() - millisInicioApagado) >= TIEMPODESCONEXION)
                        {
                              // Este if que he comentado creo que está de sobra, pues está repetido tres llaves hacia afuera.
                              //if (current <= current1*0.4 )
                              //{ 
                                    current1 = current;
                                    //Serial.println("Termino Temporizador");
                                    digitalWrite(led, LOW);         
                                    millisInicioApagado = 0;   // y reseteamos el valor de consumo y el temporizador
                              //}   
                        }
                  } 
                  else 
                  {
                        millisInicioApagado=millis();          // Iniciamos temporizado
                        //Serial.println("Comenzo temporizador");
                  }
            } 
            else 
            {
                  millisInicioApagado=0;     // Desactivamos la posible cuenta atrás
                  current1 = current ;
                  // aquí meto el digitalWrite del if que quité al principio
                  digitalWrite(led, HIGH);
            }
      }

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     

Relenchufe enchufe1(A0, 8);

void setup() 
{
      Serial.begin(9600);
}


void loop() 
{ 
      enchufe1.chequea();
      Serial.print("Corriente actual: ");
      Serial.println(enchufe1.getCurrent());
      Serial.print("Corriente máxima: ");
      Serial.println(enchufe1.getMaxCurrent());
}

Saludos.

Noter buenas noches, gracias por la clase, déjame revisarla con calma y te comento.

Hola noter, perfecto esa clase. Ahora como se utiliza? tengo entendido es como si fuese una libreria ?? como debo llamarla??? , o como es el procedimiento.

Ya que tenemos la parte de medición y comparación lista y funcionando en una clase, vamos con el siguiente paso. Dos cosas que por muy sencilla que parezcan aun no se como lo hare funcionar con la clase.

Lo que ahora necesito hacer es aparear todo esto con la aplicación app en android.

Cual es su funcionalidad, pues muy sencilla, encender el Releenchufe. Supongo esto puedo hacerlo en el voip loop principal fuera de la clase correcto ? .

La aplicacion consta de 5 botones que dicen encender, cuando se presiona el boton ella envia un dato que el arduino debe interpretar y tomar una accion, este boton pasa a un estado de color VERDE y significa la toma esta encendida. Luego que se hace la medicion y la comparacion, de ser verdadera y apagar el Releenchufe tambien debe enviar un dato a la app, para volver a colocar el boton en su estado normal y no de color verde.

El codigo con el cual probe la aplicacion es este

//Ejemplo de control de 3 LEDs mediante un módulo bluetooth y un dispositivo Android. SpainLabs.com
 
String dato;                                 //Variable de tipo cadena para guardar los datos recibidos
int rojo= 13;
int naranja= 12;
int verde= 11;
 
void setup() {
  Serial.begin(9600);                        //Iniciamos comunicación serial
   
  //Salidas digitales
  pinMode(rojo, OUTPUT); 
  pinMode(naranja, OUTPUT); 
  pinMode(verde, OUTPUT); 
  digitalWrite(13,LOW);
  digitalWrite(12,LOW);
  digitalWrite(11,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
      digitalWrite(rojo, HIGH);       //Enciende el led rojo
      delay (5000);
      Serial.println("1");                 // Enviamos dato a la aplicacion para cambiar el estado del boton
      digitalWrite(rojo, LOW);
    }
    if(dato == "2") { 
      digitalWrite(naranja, HIGH);
      delay (5000);
      Serial.println("2");
      digitalWrite(naranja, LOW);
    }
    if(dato == "3") {                        
      digitalWrite(verde, HIGH);
      delay (5000);
      Serial.println("3");
      digitalWrite(verde, LOW);
      
    }
     dato="";  //Declaramos la variable "vacía" para volver a guardar de nuevo caracteres y compararlos con cada uno de los casos
  }
}

Para recibir el dato utilizo un if y verifico si el dato == a lo que estoy enviando tomo una accion. Esto no veo problema meterlo en el voip principal fuera de la clase.

Para enviar del arduino a la aplicación un dato utilizo un serial.printl , he aqui donde veo el problema porque no se como en la clase podramos poner ese serial.printl y que envie un dato diferente segun el Releenchufe que se este utilizando. Me explico? . Se me ocurre que podriamos crear una variable, y en esa variable sea una propiedad y un parametro del Releenchufe, donde no solo se le asiganara el pin analogico y el pin del led, sino tambien que dato debe enviar por el serial.printl.

Aparte de todo y por ultimo deseo tambien crear un temporizador para una salida digital de aproximadamente 4 horas, porque? porque el modulo o la regleta contara con 2 puertos usb de carga para celulares, y tambien seran habilitados por la aplicacion, pero quiero que se apaguen automaticamente luego de un tiempo. Creo que tampoco debe haber problema de meter eso en el voip principal correcto? .

Gracias noter.

buenas perdona la pregunta

Se trata esto de un proyecto con fines educativos para aprender a usar arduino o realmente crees que puede suponer un ahorro?

La legislación actual exije a los electrodomésticos (en europa) unos consumos en stand by muy bajos, y tendrías que estudiar si realmente vale la pena tener otro aparato enchufado gastando, mas cuando este aparato es DIY que no es que este especialmente cuidado el consumo, si usas una fuente económica de 12V puede ser elevado.

Bueno. A ver qué te parece lo que he pensado.
A veces es que peco de tacaño en código y recursos, pero podemos prescindir del método getCurrent y hacer que el propio método de chequea devuelva la corriente actual (como parece que siempre vas a hacer las dos cosas, sencillamente con una sola línea de código chequeas y tomas medida). Por otro lado, tal y como está el control actualmente, creo que cuando se apaga el enchufe el valor de corriente va a ser cero, ¿no? Ahí tendrías una forma sencilla de saber si tu enchufe está apagado.
Lo único que faltaría por añadir sería un método para "armar" el enchufe.
Entonces en tu código, aparte de definir tus enchufes, por ejemplo (los puertos los asignarías según tu conexión):

Relenchufe lavadora(A1, D1), lavavajillas(A2, D2), ordenador(A3, D3);

Como hemos combinado la lectura y el chequeo, podrías:

int consumoLavadora=lavadora.chequea();
if (consumoLavadora>0)
Serial.print("Consumo de la lavadora: ");
Serial.print(consumoLavadora);
} else {
Serial.print("Enchufe de lavadora desactivado");
}

Claro; todo esto, en lugar de serial.print, enfocado a tu comunicación android en el loop.

Y la parte de armado sería algo como
if (comando=="1") lavadora.arma();

Para el armado, en teoría valdría con hacer un high en el puerto correspondiente, o al menos eso creo por ahora, ¿no? Pondré un método tal que lavadora.arma().

Me pongo a ello y en un momento te paso las modificaciones. Entiendo que el punto de partida es el código que te envié ayer, ¿no?

Bueno. Mira a ver qué puedes sacar de la clase Relenchufe ahora. Efectivamente, si has trabajado con librerías verás que casi todas implementan una o varias clases. Por eso el uso te es familiar ;). De hecho, podríamos hacer una librería para separar la clase de tu código si quieres. Primero habrá que crear otra clase para los enchufes temporizados que me decías antes y así metemos ambas en una librería. Por supuesto, creo que deberías rebautizar las clases, sus funciones/variables a un nombre más adecuado (por ejemplo, relenchufe no parece que sea muy afortunado, fue lo primero que se me pasó por la cabeza).

//////////////////////////////////////////////////////////////////////////////////
///////////////////////////////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;
};

Hola noter buenas noches, me agrada tu idea de crear otra clase para los puertos usb, solo se debe crear un temporizador para dos salidas digitales, es todo.

Ahora no entendi pero nada jajajajaja su solucion de :

Relenchufe lavadora(A1, D1), lavavajillas(A2, D2), ordenador(A3, D3);

Como hemos combinado la lectura y el chequeo, podrías:

int consumoLavadora=lavadora.chequea();
if (consumoLavadora>0)
    Serial.print("Consumo de la lavadora: ");
    Serial.print(consumoLavadora);
} else {
    Serial.print("Enchufe de lavadora desactivado");
}

y 

if (comando=="1") lavadora.arma();

A ver a mi se me ocurría algo así de crear una variable,

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

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

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

      int getMaxCurrent(){
            return(current1);
      };
      

      void 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;
                                    Serial.println(data);    // Enviamos por serial.printl a la app en android
                                    digitalWrite(led, LOW);    // Apagamos LED     
                                    millisInicioApagado = 0;   // y reseteamos el valor de consumo y el temporizador
                                 
                        }
                  } 
                  else 
                  {
                        millisInicioApagado=millis();          // Iniciamos temporizado
                  }
            } 
            else 
            {
                  millisInicioApagado=0;     // Ponemos a 0 el temporizador
                  current1 = 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;
  int data; // Variable donde pondremos el dato a enviar a la aplicacion en Android. 
  }; 


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



}

Como puedes ver en los parametros del constructor agregue la variable donde estara el dato a enviar cuando se mande apagar el led (o Relenchufe).

Relenchufe(int pinAnalog, int pinLed, int dato): 
      pinLectura(pinAnalog), led(pinLed), current1(0), millisInicioApagado(0), data(dato)

y Aqui cuando se hace la comparacion y pasa el tiempo y se cumplen todas las condiciones para apagar el Relenchufe

if ((millis() - millisInicioApagado) >= TIEMPODESCONEXION)
                        {
                               
                                    current1 = current;
                                    Serial.println(data);    // Enviamos por serial.printl a la app en android
                                    digitalWrite(led, LOW);    // Apagamos LED     
                                    millisInicioApagado = 0;   // y reseteamos el valor de consumo y el temporizador

Esto Siendo la clase como tal, que estara dentro de una libreria, ahora desde el archivo de programacion normal iría esto.

String dato;                                 //Variable de tipo cadena para guardar los datos recibidos
int led1= 8;
int led2= 9;
int led3= 10;
Relenchufe enchufe1(A0, 8, 1); //A0 entrada analoga, 8 pin de salida, 1 dato a enviar 
Relenchufe enchufe2(A2, 9, 2);
Relenchufe enchufe3(A3, 10, 3);

void setup() 
{
      Serial.begin(9600);
  pinMode(led1, OUTPUT); 
  pinMode(led2, OUTPUT); 
  pinMode(led3, OUTPUT); 
  digitalWrite(13,LOW);
  digitalWrite(12,LOW);
  digitalWrite(11,LOW);
}


void loop() 
{ 
    if (dato.length() > 0) {       //Comprueba que la variable "dato" tenga al menos un caracter 
    
    if(dato == "1") {                 //Recibimos dato y comparamos
      digitalWrite(led1, HIGH);       //Enciende el led 
    }
    if(dato == "2") { 
      digitalWrite(led2, HIGH);
    }
    if(dato == "3") {                        
      digitalWrite(led3, HIGH);
    }
     dato="";  //Declaramos la variable "vacía" para volver a guardar de nuevo caracteres y compararlos con cada uno de los casos
  }

 enchufe1.chequea();
 enchufe2.chequea();
 enchufe3.chequea();
}

Que opinas al respecto ? , solo quedaria agregar la otra clase y listo.

Buenas tardes noter, realizando pruebas todo funciona de manera perfecta.

Tanto la clase de medicion optencion del valor del sensor comparacion y acciones a tomar.

Tambien estoy realizando ya las pruebas con la app en android, efectivamente funciona el armado, enciendo el led de manera correcta.

El unico problema que tengo en este momento es el enviar un dato por el serial.println cuando se vaya apagar o desarmar el relechufe para poder reestablecer el valor inicial del boton de la aplicacion.

Te adjunto el codigo con el que realizo las pruebas.

En mi comentario anterior te comente como se me ocurrio añadir una variable al parametro del objeto o constructor para saber que dato enviar cuando ocurra el evento. Pero por lo visto de esa manera no esta funcionando.

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

class Relenchufe{
public:
      // constructor
      Relenchufe(int pinAnalog, int pinLed, int dato): 
      pinLectura(pinAnalog), led(pinLed), current1(0), millisInicioApagado(0), data(dato){
            pinMode(pinLectura, INPUT);
            pinMode(led, OUTPUT);
      };
      int getCurrent(){
            return(current);
      };

      int getMaxCurrent(){
            return(current1);
      };
      

      void 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;
                                    Serial.println(data);    // Enviamos por serial.printl a la app en android
                                    digitalWrite(led, LOW);    // Apagamos LED     
                                    millisInicioApagado = 0;   // y reseteamos el valor de consumo y el temporizador
                                 
                        }
                  } 
                  else 
                  {
                        millisInicioApagado=millis();          // Iniciamos temporizado
                  }
            } 
            else 
            {
                  millisInicioApagado=0;     // Ponemos a 0 el temporizador
                  current1 = 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;
      int data; // Variable donde pondremos el dato a enviar a la aplicacion en Android.	
	  };		


///////////////////////////////////////// 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, 1); //A0 entrada analoga, 8 pin de salida, 1 dato a enviar 
Relenchufe enchufe2(A1, 8, 2);


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
      digitalWrite(led1, HIGH);       //Enciende el led 
    }
    if(dato == "2") { 
      digitalWrite(led2, HIGH);
    }
     dato="";  //Declaramos la variable "vacía" para volver a guardar de nuevo caracteres y compararlos con cada uno de los casos
  }
  enchufe1.chequea();
  Serial.print("Corriente actual Sensor 1: ");
  Serial.println(enchufe1.getCurrent());
  delay (2000); 
  enchufe2.chequea();
  Serial.print("Corriente actual Sensor 2: ");
  Serial.println(enchufe2.getCurrent());
  delay (2000);  
}

Hola de nuevo.
Me parece que dejar unas cuestiones de la comunicación con android al loop y otras a la clase, puede ser un poco lioso, aparte de "ensuciar" la clase en sí. Lo del parámetro extra para saber desde la clase "quién soy", así no sería necesario, porque desde fuera cada objeto tiene su nombre. Si es cierto lo que te pregunté (que un enchufe apagado va a devolver cero de consumo) también tendrías solucionado lo de saber si está encendido o no desde el loop. Te pongo el código equivalente más o menos al último tuyo. Recuerda que he quitado el método getCurrent y ésta la tomo directamente del propio método chequea.

//////////////////////////////////////////////////////////////////////////////////
///////////////////////////////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);  
}

Si no es cierta la premisa anterior, creo que bastaría con una variable en la clase que pongamos a true o false cuando encendamos o apaguemos el enchufe, y un método getEncendido que nos devuelva esa variable.

Hola noter, en teoria si, cuando el enchufe este apagado la medicion cera cero porque no hay consumo de corriente .

Revisare con calma lo que adjuntaste ahorita, a ver si aclaramos eso hoy mismo para mañana no retrasarme y esperarte hasta que en la noche puedes responderme. mantente en linea por favor.

Gracias

Noter la he revisado y parece estar excelente. me gusta tu idea. mañana la probare con calma e hare la otra clase de los usb para que le heches un ojo.

Muchas gracias. buenas noches

Buenos dias Noter, curiosamente colocando el voip arma, no funciona de manera correcta, ya que los leds se prenden solos sin recibir aun el dato de la aplicacion.

Volvi a mi metodo anterior para recibir el dato de la app, pero si tomando tu metodo para enviar el dato, cuando el valor de corriente es = 0. Realizare algunas pruebas a ver como me va. Tambien e quitado tu return, aunque estaba funcionando bien no le encontre mucho sentido.

else 
            {
                  millisInicioApagado=0;     // Desactivamos la posible cuenta atrás
                  current1 = current ;
                  digitalWrite(led, HIGH);
            }
            return(current);
      }

Solo deje arriba declarado

int getMaxCurrent(){
            return(current);
      };

Que es la máxima corriente, y la que me interesa para luego imprimirla por el serial.print , y poder sumar las todas las corrientes obtenidas de los distintos sensores. y tomar una accion dependiendo del resultado.

Noter, tengo un problema que no logro entender, aun sigue sin funcionar el enviar un dato desde arduino para la aplicacion , ni de ni manera ni de la tuya.

ahora basandome unicamente en el ejemplo para probar la aplicacion :

Asi funciona perfectamente

//Ejemplo de control de 3 LEDs mediante un módulo bluetooth y un dispositivo Android. SpainLabs.com
 
String dato;                                 //Variable de tipo cadena para guardar los datos recibidos
int rojo= 6;
int naranja= 7;
int verde= 8;
 
void setup() {
  Serial.begin(9600);                        //Iniciamos comunicación serial
   
  //Salidas digitales
  pinMode(rojo, OUTPUT); 
  pinMode(naranja, OUTPUT); 
  pinMode(verde, OUTPUT); 
  digitalWrite(6,LOW);
  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") {                        //Comparamos la cadena de caracteres con cada uno de los casos
      digitalWrite(rojo, HIGH);       //Enciende el led rojo
      delay (5000);
      Serial.println("1");
      digitalWrite(rojo, LOW);
    }
    if(dato == "2") { 
      digitalWrite(naranja, HIGH);
      delay (5000);
      Serial.println("2");
      digitalWrite(naranja, LOW);
    }
    if(dato == "3") {                        
      digitalWrite(verde, HIGH);
      delay (5000);
      Serial.println("3");
      digitalWrite(verde, LOW);
      
    }
     dato="";  //Declaramos la variable "vacía" para volver a guardar de nuevo caracteres y compararlos con cada uno de los casos
     
     
     

  }
}

Mas de esta manera no funciona y lo unico que hice fue sacar los serial.println de los if.
Verifico en el monitor serial y si imprime e envia el dato.

//Ejemplo de control de 3 LEDs mediante un módulo bluetooth y un dispositivo Android. SpainLabs.com
 
String dato;                                 //Variable de tipo cadena para guardar los datos recibidos
int rojo= 6;
int naranja= 7;
int verde= 8;
 
void setup() {
  Serial.begin(9600);                        //Iniciamos comunicación serial
   
  //Salidas digitales
  pinMode(rojo, OUTPUT); 
  pinMode(naranja, OUTPUT); 
  pinMode(verde, OUTPUT); 
  digitalWrite(6,LOW);
  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") {                        //Comparamos la cadena de caracteres con cada uno de los casos
      digitalWrite(rojo, HIGH);       //Enciende el led rojo
      delay (5000);
      
      digitalWrite(rojo, LOW);
    }
    if(dato == "2") { 
      digitalWrite(naranja, HIGH);
      delay (5000);
      
      digitalWrite(naranja, LOW);
    }
    if(dato == "3") {                        
      digitalWrite(verde, HIGH);
      delay (5000);
      
      digitalWrite(verde, LOW);
      
    }
     dato="";  //Declaramos la variable "vacía" para volver a guardar de nuevo caracteres y compararlos con cada uno de los casos
     Serial.println("1");
     Serial.println("2");
     Serial.println("3");

  }
}

Pero no entiendo porque dentro de IF si la aplicacion lo toma y vuelve el boton a su estado original, y sacando el serial.println no funciona.

Bastante raro.

Hola de nuevo.
Perdona por haberte dejado solo un par de días. He estado de finde alejado de la civilización.
Efectivamente, el último código que te envié es muy probable que se encienda solo, porque sobra un digitalWrite:

            else 
            {
                  millisInicioApagado=0;     // Desactivamos la posible cuenta atrás
                  current1 = current ;
                  //digitalWrite(led, HIGH); //sobraba esta línea que hacía que se encienda solo.
            }

Lo del asunto de la comunicación con tu aplicación, tampoco veo dónde puede estar el problema; pero primero dime cómo la estableces, pues veo que usas Serial, ¿no?