AYUDA con el codigo millis

Buenas, necesito obligar al arduino a que realice la acción dentro de la condición de if(distancia1 < 20).

Estoy usando sensores de ultra sonido para localizar objetos, cuando el sensor detecte algo a una distancia menor a 20cm que encienda el led por 10 seg.

El problema es que si el sensor deja de ver el objeto antes de que culminen los 10seg por que este sigue su trayecto , termina al instante la acción dentro del if por que no se cumple la condición.

Quiero obligar a que realice la acción de encender el led por 10seg y luego apagar por 10seg una vez el sensor detecte un objeto a menos de 20cm, aun si este se pierde del rango del sensor.

Este es el código que llevo por :

//Motor
int led1=13;

//ultrasonido 1, izquierdo//
//variables
long distancia1;
long tiempo1;

//Pines
int trigger1=2; //salida de onda
int echo1=3; //entrada del eco

//Contador
int ledState = LOW; // ledState se usará para establecer el estado del LED
long previousMillis = 0; // almacenará la última vez que el estado del LED se actualizó
long interval = 10000; // intervalo del parpadeo (en milisegundos)

void setup(){

Serial.begin(9600);

pinMode(led1,OUTPUT);

//Configuracion de salida y entrada del ultrasonido 1//
pinMode(trigger1,OUTPUT);
pinMode(echo1, INPUT);

}

void loop() {

//ultrasonido 1//

//calculo de a distancia y el tiempo//
digitalWrite(trigger1,LOW); /* Por cuestión de estabilización del sensor*/
delayMicroseconds(5);
digitalWrite(trigger1, HIGH); /* envío del pulso ultrasónico*/
delayMicroseconds(10);

tiempo1=pulseIn(echo1, HIGH); /* Función para medir la longitud del pulso entrante. Mide el tiempo que transcurrido entre el envío del pulso ultrasónico y cuando el sensor recibe el rebote,
es decir: desde que el pin empieza a recibir el rebote, HIGH, hasta que deja de hacerlo, LOW, la longitud del pulso entrante*/

distancia1= int(0.017*tiempo1); /fórmula para calcular la distancia obteniendo un valor entero/

//condicion para encerder el led
if(distancia1 < 20)
{
unsigned long currentMillis = millis(); // Se toma el tiempo actual se comprueba si el tiempo actual menos el tiempo en que el LED cambió de estado por última vez es mayor que el intervalo.

if (currentMillis - previousMillis > interval) //Si se cumple la condición se guarda el nuevo tiempo en el que el LED cambia de estado
{
previousMillis = currentMillis; // Y ahora cambiamos de estado el LED, si está encendido a apagado o viceversa.
if (ledState == LOW)
{
ledState = HIGH;
}
else
{
ledState = LOW;
}
digitalWrite(led1, ledState); // Hacemos que el contenido de la variable llegue al LED
}
}

else
{
digitalWrite(led1, LOW);
}

Serial.println("Distancia ");
Serial.println(distancia1);
Serial.println(" cm");

}

Para hacer eso debo analizar tu rutina. Porque escribes o copias una rutina del un sensor ultrasónico cuando existe una librería probada que garantiza unbuen funcionamiento.

Yo usaría la librería que te indico y verás que no tienes problema.

NOTA:

  1. usa tags para insertar códigos.
  2. Indica que sensor estas usando.

Hola elvisnoria , primero como dijo surbyte usa los tags correspondientes para postear el código sino es todo un lío.

Segundo, porque no haces lo siguiente? :

if(objetoamenosde20cm) {

Digitalwrite(pinled,HIGH);
Delay(cantidad de tiempo);
Digitalwrite(pinled,LOW);

}

El codigo anterior es a modo de ejemplo, pero a lo que voy es a que porque no utilizas delay()?

francosalda:
Hola elvisnoria , primero como dijo surbyte usa los tags correspondientes para postear el código sino es todo un lío.

Segundo, porque no haces lo siguiente? :

if(objetoamenosde20cm) {

Digitalwrite(pinled,HIGH);
Delay(cantidad de tiempo);
Digitalwrite(pinled,LOW);

}




El codigo anterior es a modo de ejemplo, pero a lo que voy es a que porque no utilizas delay()?

Si es lo único que se va a hacer si funcionaria, pero si se tiene que hacer algo mas se quedaría estancado, por ejemplo hacer sonar un buzzer cada vez que un objeto este cerca y apagarlo cuando se retire.

Este tipo de acciones requieren sensores activos la mayor parte del tiempo, con un delay tan grande en el código quedaría "ciego".

Saludos.

No se que pretendes hacer con esto al final, pero usar delay para 10 seg es mucho como te estan diciendo, yo prefiero usar banderas de indicacion.

Este sketch, estará censando constantemente y enviando la medición por vía serial. En el momento que detecte que la distancia es menor a 20 cm, encenderá el led1, y este estará encendido durante 10 seg. y el programa seguirá su funcionamiento, al finalizar los 10 s se apagara el led1 y esperara 10 s mas para volver a comprobarse la condición ( distancia < 20 ).

Aunque el led este encendido o en estado de espera la distancia se estará midiendo y enviando por serial.

//Motor
int led1=13; 

//ultrasonido 1, izquierdo//
//variables
long distancia1;
long tiempo1;

//Pines 
int trigger1=2;   //salida de onda
int echo1=3;  //entrada del eco

//Contador
int ledState = LOW;   // ledState se usará para establecer el estado del LED
long previousMillis = 0;   // almacenará la última vez que el estado del LED se actualizó
long interval = 10000;   // intervalo del parpadeo (en milisegundos)

bool encender   = false;
bool esperar    = false;
unsigned long currentMillis = 0;

void setup(){
  Serial.begin(9600); 
  pinMode(led1,OUTPUT);
  pinMode(trigger1,OUTPUT);
  pinMode(echo1, INPUT); 
 
}

void loop() {
  digitalWrite(trigger1,LOW); /* Por cuestión de estabilización del sensor*/
  delayMicroseconds(5);
  digitalWrite(trigger1, HIGH); /* envío del pulso ultrasónico*/
  delayMicroseconds(10);
  
  tiempo1=pulseIn(echo1, HIGH); 
  distancia1= int(tiempo1/58.0); 

  if(distancia1 <= 20 && !encender) {
    encender = true;
    currentMillis = millis();
    digitalWrite(led1, HIGH);
  }

  if((millis() - currentMillis> interval) && !esperar && encender){
    esperar = true;
    digitalWrite(led1, LOW);
    currentMillis = millis();
  }
  if((millis() - currentMillis> interval) && esperar){
    encender = false;
    esperar  = false;
  }



  Serial.println("Distancia ");
  Serial.println(distancia1);
  Serial.println(" cm");   
  

}

2 dias sin respuesta.....mmm

El problema es el siguiente:

Estoy trabajando con un riel de impresión y este usa motor dc, en el riel de impresión desplazare la base del cartucho hasta una posición x, hacer esto con un motor de paso seria muy fácil de hacer por que se calculan la cantidad de pasos que tendría que realizar el motor para que la base del cartucho llega a la posición "x", pero con un motor DC no se puede, entonces voy a controlar la posición de la base del cartucho por tiempo, encendiendo y apagando el motor por un tiempo determinado, 10seg es el tiempo de prueba para ver si el código funcionaba.

También quería que el motor encendiera y apagara el tiempo establecido (10seg use de ejemplo) así el objeto se fuera de rango ya que necesito que la base del cartucho llegue a la posición "x" y regrese a la posición inicial.

Otra duda, esa acción dentro del if necesito que se repita una vez, es decir, detecto algo, desplazo la base del cartucho a una distancia "x" manteniendo el motor encendido un tiempo "t1", este se apaga un tiempo "t2" y finalmente se enciende otra vez el motor un tiempo "t1" para que regresar a su posición inicial, esperar si el sensor detecta algo para repetir las acciones. Pero no veo la manera o el como incluir un ciclo for en el código.

Vi que usando el currentMillis es la forma mas fácil de hacerlo. Por que no usaría delay si no que trabajaría como con una especie de contador o timer.

Disculpen por no responder, tenia problemas con mi servidor de Internet. Probare el código del amigo max_saeta. De verdad agradezco que se tomen siempre las molestias de responder a mis dudad, mañana les comento como me fue con el código que me recomendó el amigo.

//Motor//
int motor1=13; //Giro a la izquierda
int motor2=12; //Giro a la derecha
int pwm1;      //Variable del PWM 1
int pwm2;      //Variable del PWM 1


//ultrasonido 1, izquierdo//
//variables
long distancia1;
long tiempo1;

//Pines 
int trigger1=2;   //salida de onda
int echo1=3;  //entrada del eco


//Ultrasonido 2, derecho//
//Variables
long distancia2;
long tiempo2;

//Pines
int trigger2=5;   //salida de onda
int echo2=6;  //entrada del eco


//Contador//
int motorState = LOW;   // Se usará para establecer el estado del Motor
long previousMillis = 0;   // almacenará la última vez que el estado del motor se actualizó
long interval = 10000;   // intervalo del parpadeo (en milisegundos)



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

  //Configuracion de giro de los motores//
  pinMode(motor1,OUTPUT);
  pinMode(motor2,OUTPUT);
  
  //Configuracion de salida y entrada del ultrasonido 1//
  pinMode(trigger1,OUTPUT);
  pinMode(echo1, INPUT); 
 
  //Configuracion de salida y entrada del ultrasonido 2//
  pinMode(trigger2,OUTPUT);
  pinMode(echo2, INPUT); 

}

void loop() {
  
  //Como la entrada analógica del Arduino es de 10 bits, el rango va de 0 a 1023. En cambio, la salidas del Arduio son de 8 bits, quiere decir, rango entre 0 a 255.
  //Por esta razón tenemos que mapear el número de un rango a otro usando este código.
  pwm1 = map(valorpote, 0, 1023, 0, 255);
  pwm2 = map(valorpote, 0, 1023, 255, 0); //El PWM 2 esta invertido respecto al PWM 1
  // usaría esto si necesitara controlar la velocidad de giro, aun estoy viendo si usarlo o no
  
  //ultrasonido 1//
  
  //calculo de a distancia y el tiempo//
  digitalWrite(trigger1,LOW); /* Por cuestión de estabilización del sensor*/
  delayMicroseconds(5);
  digitalWrite(trigger1, HIGH); /* envío del pulso ultrasónico*/
  delayMicroseconds(10);
  
  tiempo1=pulseIn(echo1, HIGH); /* Función para medir la longitud del pulso entrante. Mide el tiempo que transcurrido entre el envío del pulso ultrasónico y cuando el sensor recibe el rebote, 
  es decir: desde que el pin empieza a recibir el rebote, HIGH, hasta que deja de hacerlo, LOW, la longitud del pulso entrante*/
  distancia1= int(0.017*tiempo1); /*fórmula para calcular la distancia obteniendo un valor entero*/
 
  //condicion para dezplasar el motor a la izquierda//
  if(distancia1 < 20)
 {
   unsigned long currentMillis = millis();    // Se toma el tiempo actual se comprueba si el tiempo actual menos el tiempo en que el LED cambió de estado por última vez es mayor que el intervalo.
   
   if (currentMillis - previousMillis > interval)  //Si se cumple la condición se guarda el nuevo tiempo en el que el LED cambia de estado
   { 
       previousMillis = currentMillis; // Y ahora cambiamos de estado el LED, si está encendido a apagado o viceversa.
       if (motorState == LOW)
       {
            motorState = HIGH;
       }
       else
       {
            motorState = LOW;
       }
   analogWrite(motor1, motorState);  // Hacemos que el contenido de la variable llegue al LED
   }  
 }
 
 else
 {
   analogWrite(motor1, LOW);
 }
  
  Serial.println("Distancia ");
  Serial.println(distancia1);
  Serial.println(" cm");   

}

En el código con el que inicie el tema, utilice led´s para simular el envió de señales al puente H, para ver si enviaba una señal para hacer girar el motor a la derecha o izquierda.

Uso dos sensores, uno para detectar objetos a la izquierda del riel y girar el motor a la izquierda, y otro a la derecha del riel para hacer girar el motor a la derecha.

elvisnoria:
Estoy trabajando con un riel de impresión y este usa motor dc, en el riel de impresión desplazare la base del cartucho hasta una posición x, hacer esto con un motor de paso seria muy fácil de hacer por que se calculan la cantidad de pasos que tendría que realizar el motor para que la base del cartucho llega a la posición "x", pero con un motor DC no se puede, entonces voy a controlar la posición de la base del cartucho por tiempo, encendiendo y apagando el motor por un tiempo determinado, 10seg es el tiempo de prueba para ver si el código funcionaba.

Bueno yo hace poco estuve haciendo un Plotter , y sinceramente no te entendi bien para que vas a utilizar especificamente el motor.
Si vas a utilizar ese motor DC para que regrese a su base y calculas que tardara 10 segundos (por decir un ejemplo..pueden ser 5 segundos,3 segundos, lo que quieras) no es asi ya que puede encontrarse en diferentes posiciones, por ejemplo digamos que tarda 10 segundos en volver desde el final del "riel" hasta el inicio, en caso de encontrarse en la mitad y volver el motor quedaria atascado provocando sobrecalentamiento por un breve periodo de tiempo. Esto lo podrias arreglar poniendo un final de carrera.
Me explico mejor : puedes hacer que el motor vuelva ala posición inicial sin importar en donde este , poniendo un final de carrera que corte la corriente del motor al llegar a la base.

Si por otra parte lo que quieres es manejar la posición con un motor DC, por tiempo , vas a tener algo muy impreciso e inexacto, yo ya anduve haciendo pruebas con eso. Las impresoras con motores DC , llevan un encoder con lo que van contando las "vueltas del motor " para manejar la precisión.

Si quieres precisión mejor utiliza un motor PAP o sino ve si puedes decifrar algun encoder (yo no pude ..)

Saludos

Saludos
Para usar un motor DC hay una solución. Unir el motor a un encoder rotativo para saber en que posición esta.

Yo personalmente creo que hay que explicar el objetivo de nuestro trabajo para poder recibir las mejores sugerencias que se conozcan. Si hubieses explicado eso al inicio te hubiese recomendado los del encoder.

Tienen toda la razón, disculpen por eso. El cartucho llegara al final del riel de impresión, nunca se va a detener a una distancia aleatoria. Su trayecto sera de extremo a extremo. el riel mide 50cm, entonces su posición inicial seria 0cm y la final 50cm, siempre sera así.

Dando el ejemplo que la base del cartucho en desplazarse de un extremo a otro tarde le tome 10seg, ¿como me quedaría el código final?.

Por eso necesito obligar la acción del motor una vez el objeto entre en el rango del sensor y así este se pierda o salga del rango.

Bueno la solucion mas facil, economica y practica: Usar finales de carrera: