Controlar leds a lo StarWars

Hola Me llamo David y me estoy iniciando en este mundillo.

Mi primer proyecto, es una tira de leds que se encienda desde un sensor de ultrasonidos hc-sr04, cuando pase la mano por delante entre 7 y 30 cm.

Ya lo tengo realizado y me funciona casi de maravilla, digo casi por que me encuentro que si no le pongo el potenciómetro, los leds, no se iluminan con suficiente fuerza (a un 15% de su rendimiento aprox.) pero funciona a las mil maravillas, si le pongo el potenciómetro y se lo aplico con su código, los leds dan el 100% del rendimiento pero... se van encendiendo y apagando.

La verdad es que no se que es lo que me falla y por eso me gustaría a ver si alguien pudiese echarme una mano o darme algún consejo.

Muchas Gracias a todos por adelantado.

Aquí os dejo el código y unas fotos:

Este es el esquema que he seguido para conectarlo, cambiando el botón por el hc-sr04.

#include <Ultrasonic.h>

Ultrasonic ultrasonic(9,8); // (Trig PIN,Echo PIN)
int led = 11;
bool encendido = false;

void setup() {
Serial.begin(9600); //Inicio Consola de seguimiento
}

void loop()
{
Serial.print(ultrasonic.Ranging(CM)); // CM or INC
Serial.println(" cm" );
if ((ultrasonic.Ranging(CM) < 30 && !encendido) && (ultrasonic.Ranging(CM) > 7 && !encendido)) {
digitalWrite(led, HIGH);
encendido = true;
delay(2000);
} else if (ultrasonic.Ranging(CM) < 30 && encendido){
digitalWrite(led, LOW);
encendido = false;
delay(2000);
}
int lectura = analogRead(A0); // Leemos A0
analogWrite (led, lectura / 4); // Ponemos la tension de control
delay(100);
}





Un problema que he encontrado con el código, es que indiferentemente de la proximidad que detecta el sensor, está aplicando el analogWrite; eso hace que se encienda y se apague.

Te sugiero que cambies...

digitalWrite(led, HIGH);

por:

int lectura = analogRead(A0);       // Leemos A0
analogWrite (led, lectura / 4);       // Ponemos la tension de control
delay(100);

Y obviamente borrar esas líneas que están después del bloque del else if.

Respecto a lo del potenciometro, el código está hecho para regular el brillo de los LEDs con base en este; si lo quitas, es obvio que luego queden tenues...

Gracias por tu consejo, ya lo he modificado, pero :(... Los LED's cuando paso la mano se encienden y a lo que pasa el tiempo del delay que le ponga se apagan solos.
lo miro en el monitor pasando los parámetros de la lectura del ultrasonido y otra de variable booleana y en principio tendría que ir a las mil maravillas, se enciende y se apaga al pasar la mano, pero a la que le doy los 12v, pasa el delay y me apaga los LED's.

De momento el código me a quedado así:

#include <Ultrasonic.h>

Ultrasonic ultrasonic(9,8); // (Trig PIN,Echo PIN)
int led = 11;
bool encendido = false;

void setup() {
  Serial.begin(9600); //Inicio Consola de seguimiento
}

void loop()
{
  Serial.print(ultrasonic.Ranging(CM)); // CM or INC
  Serial.println(" cm" );
    if ((ultrasonic.Ranging(CM) < 30 && !encendido) && (ultrasonic.Ranging(CM) > 7 && !encendido)) {
      int lectura = analogRead(A0);       // Leemos A0
      analogWrite (led, lectura / 4);       // Ponemos la tension de control
      encendido = true;
      Serial.println(encendido);
      Serial.println("encendido");
      delay(1000);
      
    } else if (ultrasonic.Ranging(CM) < 30 && encendido){
      //digitalWrite(led, LOW);
      analogWrite (led, 0);
      encendido = false;
      Serial.println(encendido);
      Serial.println("apagado");
      delay(1000);
    }

  delay(200);  
}

El delay del final lo quite o no me hace lo mismo.

Me tiene desesperado :confused: no se por donde pillarlo.

De todas maneras muchas gracias Lucario448. Algo he ganado :wink: si ves algo mas o alguien ve algo, se lo agradeceré en el alma por que no me deja dormir, tiene que ser una tontería pero no la veo y no se si es la parte de código o la parte física.

En fin... de nuevo gracias por la ayuda!

Otra cosa, deshaste de la variable "encendido" y las condicionales que lo involucran, porque creo que lo que necesitas es que "led" se encienda entre los 7 y 30 cm de proximidad; y se apague fuera de ese rango.
Ese código así como está, no te va a permitir cambiar el brillo después de la primera pasada por el primer if, a no ser que la proximidad esté de nuevo fuera del rango.

En otras palabras, si lo que quieres es poder actualizar el brillo constantemente mientras esté dentro del umbral, deshaste de esa variable y de las veces que se utiliza. O tenías en mente otra cosa?

Vengo leyendo el avance de este proyecto y no termino de comprender tu objetivo. Dices:

Mi primer proyecto, es una tira de leds que se encienda desde un sensor de ultrasonidos hc-sr04, cuando pase la mano por delante entre 7 y 30 cm.

Okay, eso esta.
Luego resultó que el código modificaba el brillo en función de un potenciómetro.
Que quieres hacer? que el brillo se modifique en función de esa distancia?
Si es 7 cm cuanto brillo? 0 o 100%?
Y lo mismo para 30 cmts o te entiendo mal?

Perdonad, igual no me explique bien!
El objetivo o lo que pretendo es que al pasar la mano entre 7 y 30 cm los LED's se enciendan al 100% de su luminosidad y al volver a pasar la mano entre 7 y 30 cm se apaguen, osea la mano sería a modo interruptor on/off.

Con lo que me dijo LUCARIO448, los LED's se encienden al 100% ya que el potenciometro lo tengo a tope, pero en cuanto me pasa el tiempo del delay que le marque se me apagan solos, si quito la parte del codigo del potenciometro de analogWrite los LED's no brillan en toda su intensidad pero funciona perfectamente (se enciende al pasar la mano y cuando vuelvo a pasar la mano se apagan) :frowning:

Espero haberme explicado mejor.
Muchas gracias por vuestra atención y ayuda!

xdavidx:
El objetivo o lo que pretendo es que al pasar la mano entre 7 y 30 cm los LED's se enciendan al 100% de su luminosidad y al volver a pasar la mano entre 7 y 30 cm se apaguen, osea la mano sería a modo interruptor on/off.

Entonces por qué en el código que posteaste la primera vez, usaste el analogWrite?
Por cierto, ahora que me lo dejaste más claro... no debí sugerirte que borraras aquella variable... ::slight_smile:

pero en cuanto me pasa el tiempo del delay que le marque se me apagan solos

Entonces también quieres ponerle un tiempo límite de encendido? O me equivoco?

si quito la parte del codigo del potenciometro de analogWrite los LED's no brillan en toda su intensidad

Aún usando digitalWrite(led, HIGH)?

Lo de analogWrite lo hice por que es la única manera que encontré para que los LED's brillaran a su 100%.
la verdad es que si pudiese evitar de poner el potenciómetro por mi mucho mejor, pero si lo quito y borro las lineas de analogWrite los LED's están a una intensidad muy baja, pero el código funciona perfecto y hace lo que quiero que haga.

En cuanto a lo del DELAY se me apagan solos, yo no quiero que se apaguen hasta que vuelva a pasar la mano por delante :frowning:

Y como he puesto arriba aún usando digitalWrite(led, HIGH) los LED's brillan aun 10% aproximadamente de su potencia.

Estoy empezando a pensar que mas que de la parte del código es de la parte física, ¿Podría ser?

Si queréis os hago un vídeo para que veáis como me funciona de una manera y de la otra. ;(

Aca tienes tu problema resuelto.
Cabe mencionar que no hace falta usar ni analogRead(A0) ni analogWrite pero te deje las opciones para que controles el brillo si lo usas.
Ahora esta a FULL o seaprende al 100 o apaga a 0 (siempre apagará a 0).

#include <Ultrasonic.h>

Ultrasonic ultrasonic(9,8); // (Trig PIN,Echo PIN)
int led           = 11;
bool encendido    = false;

void setup() {
  Serial.begin(9600); //Inicio Consola de seguimiento
}

void loop() {
  Serial.print(ultrasonic.Ranging(CM)); // CM or INC
  Serial.println(" cm" );
  rango = ultrasonic.Ranging(CM);
  int lectura = map(analogRead(A0), 0, 1023, 0, 100); // esto te convierte la posicion del potenciometro a salida 0-100%
  
  if ( rango > 7 && rango < 30)
      encendido = !encendido;
    
  if (encendido) {
      digitalWrite(led, HIGH);  // esto es al 100%
      //analogWrite(led, lectura); // Si quieres control de brillo usa esta linea
  }
  else {
      digitalWrite(led, LOW);
      //analogWrite(led, 0); // Si quieres control de brillo usa esta linea
    }
  }
}

Extraño...

digitalWrite(led, HIGH) no debería provocar atenuación alguna.
Así para descartar, crees que puedas cambiar el pin de los LEDs por otro que no sea capaz de producir PWM? (por ejemplo, el 13)

Mirar aquí os dejo estos vídeos:

Este enlace seria con la atenuación de los LED's, pero funcionando perfectamente (lastima de la atenuación :()

Atenuados

Con el siguiente código:

#include <Ultrasonic.h>

Ultrasonic ultrasonic(9,8); // (Trig PIN,Echo PIN)
int led = 11;
bool encendido = false;

void setup() {
  Serial.begin(9600); //Inicio Consola de seguimiento
}

void loop()
{
  Serial.print(ultrasonic.Ranging(CM)); // CM or INC
  Serial.println(" cm" );
    if ((ultrasonic.Ranging(CM) < 30 && !encendido) && (ultrasonic.Ranging(CM) > 7 && !encendido)) {
      digitalWrite(led, HIGH);
      //int lectura = analogRead(A0);
      //analogWrite (led, lectura / 4);
      encendido = true;
      delay(1000);
    } else if ((ultrasonic.Ranging(CM) < 30 && encendido) && (ultrasonic.Ranging(CM) > 7 && encendido)){
      digitalWrite(led, LOW);
    //  analogWrite (led, 0);
      encendido = false;
      delay(1000);
    }
  delay(100);  
}

LED's al 100% pero se apagan solos :frowning:

Con el siguiente código:

#include <Ultrasonic.h>

Ultrasonic ultrasonic(9,8); // (Trig PIN,Echo PIN)
int led = 11;
bool encendido = false;

void setup() {
  Serial.begin(9600); //Inicio Consola de seguimiento
}

void loop()
{
  Serial.print(ultrasonic.Ranging(CM)); // CM or INC
  Serial.println(" cm" );
    if ((ultrasonic.Ranging(CM) < 30 && !encendido) && (ultrasonic.Ranging(CM) > 7 && !encendido)) {
      //digitalWrite(led, HIGH);
      int lectura = analogRead(A0);
      analogWrite (led, lectura / 4);
      encendido = true;
      delay(1000);
    } else if ((ultrasonic.Ranging(CM) < 30 && encendido) && (ultrasonic.Ranging(CM) > 7 && encendido)){
     // digitalWrite(led, LOW);
      analogWrite (led, 0);
      encendido = false;
      delay(1000);
    }
  delay(100);  
}

Y Lucario448 Acabo de probar de ponerlo en el 13 y... :frowning: Me da la misma intensidad que el primer video.
Empiezo a desesperarme un poco :frowning:

Creo que ya lo empiezo a visualizar todo. Por alguna razón, el TIP120 se vuelve más conductor con PWM que con 5v constantes.

Tienes dos opciones:

  • Reemplazar el transistor por un MOSFET como el IRFZ34 (N).
  • Quedarte con el segundo código, quitar el potenciómetro y colocarle valores prefijados al analogWrite (0 es apagado, 255 es al 100%)

El segundo código lo he modificado un poco. Prueba a ver qué tal:

#include <Ultrasonic.h>

Ultrasonic ultrasonic(9, 8); // (Trig PIN,Echo PIN)
const byte led = 11; // Una pequeña optimización. Ahora esta variable ocupa menos espacio en la memoria
bool encendido = false;

void setup() {
  Serial.begin(9600); // Inicio Consola de seguimiento
  pinMode(led, OUTPUT); // Te faltó esta parte
}

void loop()
{
  Serial.print(ultrasonic.Ranging(CM)); // CM or INC
  Serial.println(" cm" );
  if ((ultrasonic.Ranging(CM) < 30) && (ultrasonic.Ranging(CM) > 7) && !encendido) { // La variable "encendido" basta con que se pruebe una sola vez
    //digitalWrite(led, HIGH);
    analogWrite (led, 255);
    encendido = true;
    delay(1000);
  } else if ((ultrasonic.Ranging(CM) < 30) && (ultrasonic.Ranging(CM) > 7) && encendido) { // La variable "encendido" basta con que se pruebe una sola vez
    // digitalWrite(led, LOW);
    analogWrite (led, 0);
    encendido = false;
    delay(1000);
  }
  delay(100);
}

Gracias xdavix por no mirar el código que te pasé!

Prueba la interface de los LEDs y el TIP120 conectando solo a GND la resistencia de base.
Si los leds siguen algo encendidos entonces algo ocurre pero dudo que eso pase.

surbyte:
Gracias xdavix por no mirar el código que te pasé!

No sé por qué el tuyo no lo vio; está hasta más fácil de entender. Lo único que le cambiaría, es comentar la línea que lee el potenciómetro; y agregar pinMode(led, OUTPUT); a la función setup.

Porque hay que comentar la linea del potenciómetro?
Tal vez el quiera que los les se enciendan con algun nivel de brillo diferente del 100% por eso lo dejé por si asi lo quiere hacer.
Y tienes razon con agregarlo

pinMode(led, OUTPUT);

si lo usa con la alternativa que le he dejado habilitada.

Hola perdona subyte! Si que lo prove tu código! Pero aun me hacia mas el loco, ya te hare un video con el resultado de tu código para enseñartelo, lo siento por no contestarte, acabo de ser padre y se puso un poco revelde la niña y se me paso decirte nada. Mil disculpas!
Acabare de probar tu código y te hare un video con el resultado, que lo probare con mas calma! A lo largo de hoy te digo el que... :slight_smile:

Bueno aquí tengo los resultados, surbyte hay uno que roza el larguero :wink:

Código tal cual esta arriba

le añadí un delay(1000) para que me diera tiempo a pasar la mano por delante sino ya lo ves se enciende y se apaga demasiado rápido, aunque los LED's siguen sin brillar :frowning:

Código igual pero con delay(1000)

Esta es la mejor opción hasta el momento es tu código cogiendo la parte de analógico y con delay(1000) los LED's brillan al 100% pero tiene micro oscilaciones, los ultrasonidos funcionan pero fallan un poco y de vez en cuando se apagan solos.
Creo que lo de las oscilaciones se puede apreciar un poco en el vídeo.

Surbyte analógica delay(1000)

En fin aún falla pero esta última prueba me da esperanzas :slight_smile:

Por cierto no entendí esto:
Puedes explicármelo de otro modo, creo que soy demasiado novato aún :frowning:

Prueba la interface de los LEDs y el TIP120 conectando solo a GND la resistencia de base.
Si los leds siguen algo encendidos entonces algo ocurre pero dudo que eso pase.

El TIP120 ahora mismo lo tengo mirándolo de frente de izquierda a derecha:

_ Pin 11 a través de una resistencia de 1k.
_ Al negativo de los LED's.
_ Al negativo de los 12v y a GND.

xdavidx:
los LED's brillan al 100% pero tiene micro oscilaciones.

Eso es por una señal PWM. PWM no genera un nivel de voltaje estable; sino que lo simula conmutando el pin muy rápidamente.

El TIP120 ahora mismo lo tengo mirándolo de frente de izquierda a derecha:

_ Pin 11 a través de una resistencia de 1k.
_ Al negativo de los LED's.
_ Al negativo de los 12v y a GND.

A como nos mostraste desde el primer post, lo tienes bien colocado. Lo que me tiene en duda, es que si la resistencia que le colocaste en serie a la base del transistor, le permite entrar en saturación (volverse completamente conductor).
Según de lo que he leído de la hoja de datos ("datasheet"), el voltaje de saturación (encendido) es de 2,5v.
Carga el código que usa los digitalWrite, enciende los LEDs, y búscate un multímetro para medir el voltaje entre base y emisor. Si la lectura da menos de los 2,5v, entonces puede que el valor de esa resistencia sea muy alto.

Pero estamos a oscuras. No sabemos que corriente toman los LEDs menos podemos establecer que valor tendrá la resistencia de Base.

Mi prueba es simple. Si dejas todo como esta pero retiras la conexión que va desde la resistencia de base al arduino y la pones a GND. Y los leds no se encienden entonces no hay nada de que preocuparse
De hecho en el video que publicaste todo luce bien, falta mejorar la respuesta del ULTRASONICO que da muchos valores y el sistema se redispara.

Ahora te modifiqué el código para que responda a un retardo de cambio. Tanto de encendido como apagado.
Lo puse en 500 mseg pero ajusta al valor que desees

#include <Ultrasonic.h>
#define  INTERVALO    500   // ajustar retardo al valor que se desee

Ultrasonic ultrasonic(9,8); // (Trig PIN,Echo PIN)
int led           = 11;
bool encendido    = false;
int  rango;

void setup() {
  Serial.begin(9600); //Inicio Consola de seguimiento
  pinMode(led, OUTPUT);
}

void loop() {
  char buffer[30];

  rango = ultrasonic.Ranging(CM);
  sprintf(buffer, "%d cm", rango)	
  Serial.println(buffer);
  
  //int lectura = map(analogRead(A0), 0, 1023, 0, 100); // esto te convierte la posicion del potenciometro a salida 0-100%
  
  if (rango > 7 && rango < 30 && millis() > retardo)) {
      encendido = !encendido;
      retardo = millis() + INTERVALO;
  }
    
  if (encendido) {
      digitalWrite(led, HIGH);  // esto es al 100%
      //analogWrite(led, lectura); // Si quieres control de brillo usa esta linea
  }
  else {
      digitalWrite(led, LOW);
      //analogWrite(led, 0); // Si quieres control de brillo usa esta linea
  }
}

surbyte:
No sabemos que corriente toman los LEDs

Corriente en amperaje o estas hablando del flujo de corriente?

Amperaje: creo que ronda los 2 amperios si están al 100%
Flujo de corriente: positivo de los LEDs al positivo de una fuente de 12v; entre el negativo de los LEDs y tierra, tenemos el transistor. Esto debido a que es de polaridad NPN, o mejor dicho: "va al tierra del consumidor, y conduce cuando se le aplica voltaje a la base".