Go Down

Topic: Pico de luz con PWM (Read 995 times) previous topic - next topic

Mikms

Feb 16, 2020, 07:20 pm Last Edit: Feb 24, 2020, 10:56 pm by Mikms
Hola a todos. A ver , tengo una luz PWM para una mini lámpara.

La idea es luz variable en intensidad mediante dos botones,
-uno para subir y
-otro para bajar la intensidad,
-además de un tercer boton que este lo que hace es apagar la luz directamente esté la intensidad donde esté.


El problema está en que si la luz la pongo a cualquier intensidad que no sea la máxima va todo correcto, o si la pongo al máximo y la bajo con el segundo boton (bajar intensidad), pero si la pongo a maxima intensidad (que ya parpadea el led rojo) y apago desde el boton de apagado (tercer boton) si le doy a encender progresivamente nuevamente la luz, está lo primero que hace es que da un pico de intensidad y seguido comienza a subir poco a poco, pero lo primero siempre es un pico que es molesto.

A continuacion dejo el sketch (aunque terminaría montando con un attiny 85 por cuestion de tamaño)

Code: [Select]




#include <elapsedMillis.h>

elapsedMillis timeElapsed;


//Patillas
     const int ledPinOUT = 9;      //PIN6 --> Patilla 5 del Attiny, es el que tendrá asignada la salida de luz regulable y es un pin PWM
     const int ledPinROJO = 5;     //PIN7 --> Patilla 6 del Attiny,
     const int botonOFF = 2;     // PIN0 the number of the pushbutton pin
     const int botonSumaPin = 3 ;   //PIN1 --> Patilla 2 del Attiny , es el boton que sumara (1 en este caso) al ciclo de trabajo subir luz
     const int botonRestaPin = 4;  //PIN2 --> Patilla 3 del Atinny , es el boton que restara (1 en este caso) al ciclo de trabajo bajar luz
     
// Variables
    int botonSumaValue;           //Variable para el boton de suma
    int botonRestaValue;          //Variable para el boton de resta
    byte cicloTrabajo=0;            //Variable para el ciclo de trabajo del led



// retraso en milisegundos entre parpadeos del LED
unsigned int interval = 50;

// estado del LED = LOW está apagado, HIGH está encendido
boolean ledState = LOW;
volatile int i = 0; // inicializando un entero para incrementar y disminuir la relación de trabajo.


//inicialización
void setup(){
    pinMode(ledPinOUT, OUTPUT);
    pinMode(ledPinROJO, OUTPUT);
    pinMode(botonSumaPin, INPUT);
    pinMode(botonRestaPin, INPUT);
    pinMode(botonOFF, INPUT);

 // Serial.begin(9600);
  }

void loop (){
    botonSumaValue= digitalRead(botonSumaPin);
    botonRestaValue= digitalRead(botonRestaPin);
   cicloTrabajo = constrain(cicloTrabajo, 0, 200);
 
 //Serial.println(cicloTrabajo);
 
 if (  cicloTrabajo <150 && botonSumaValue == HIGH ){
    cicloTrabajo++;

   
 
  }
   
 

 
    if ( cicloTrabajo >=1 && botonRestaValue == HIGH){
       cicloTrabajo--;    //Disminuye el brillo si se presiona el pulsador

  }
  analogWrite(ledPinOUT, cicloTrabajo);    //Modifica el brillo del LED por medio de una señal PWM
  delay(15);


    if (cicloTrabajo ==0)
    analogWrite(ledPinROJO, 200);
    else
    analogWrite(ledPinROJO, 0);


    if (botonSumaValue == HIGH && cicloTrabajo >=149)
    {

 

      ledState = !ledState;         // cambiar el estado de ALTO a BAJO a ALTO a BAJO ...
      digitalWrite(ledPinOUT, ledState);
      timeElapsed = 0;            // restablecer el contador a 0 para que el conteo comience de nuevo ...
  }
    delay(10);

 if (digitalRead(botonOFF) == HIGH)

{


 cicloTrabajo =0;

 analogWrite(ledPinOUT, cicloTrabajo);

delay (10);
}
}



}

Sereno

Si no he entendido mal, cuando apagas con un nivel diferente al máximo, al encender de nuevo no se produce ese pico es así??
Prueba a verificar que no sea problema de tu hardware, monitoriza por el serial el valor de la variable cicloTrabajo, a ver si empieza desde un valor diferente cuando apagas desde un valor máximo o desde un valor diferente.

Mikms

Exacto asi es, cuando bajo la intensidad o no la llevo al máximo y apago desde el botón APAGAR, empieza encendiendo sin problema, va perfecto (o sea poco a poco), pero cuando la subo al máximo y apago desde el botón APAGAR, al comenzar de nuevo siempre da un pico, algo asi como "máximo-apagarse-comenzar ciclo" muy rápido (que realmente sobrepasa el máximo, ya que se que es máximo y ya no sube más porque si continuo pulsando SUBIR parpadea a la vez el led rojo, que está puesto para avisar de ello). Con Arduino lo hace más leve, e incluso a veces no lo hace, pero con Attiny es realmente molesto y mucho más acusado.

Probaré y lo comento, gracias Sereno


Mikms

Bueno despues de probarlo con el puerto serie marca todo correcto, sube linealmente hasta 255, baja hasta 0 cuando pulso el boton APAGAR, y al subir (sigue dando el pico de luz) pero comienza desde 0 y sube linealmente sin ningun salto ni nada en las indicaciones del puerto serial.
 
Ya habia probado antes si podría ser que el boton diera algun tipo de fallo por rebote etc, pero eso tampoco me lo ha solucionado.

Ahora mismo realmente no sé que puede ser lo que provoca esto

surbyte

#4
Feb 17, 2020, 03:48 pm Last Edit: Feb 17, 2020, 04:02 pm by surbyte
Esto que es o qué crees que hace porque esta mal programado

Code: [Select]
if (ledPinOUT, cicloTrabajo <1)

debe ser

Code: [Select]
if (cicloTrabajo <1)


Tu otro problema es la mala elección del tipo de variable a incrementar.
analogWrite() solo permite 0 a 255 o sea 8 bits y has definido variables como entero o sea int cicloTrabajo.
Eso permite llegar hasta 32765 y supongamos que no sea el caso.. y que solo llegue a 500, es posible, claro que es posible, porque tu código no limita eso.

un par de cambios simples harían desparacer tu brillo en los márgenes límites

Code: [Select]
byte cicloTrabajo = 0;

y las variables de los botones solo bool ni siquiera int.


Prueba esto

Code: [Select]
#include <elapsedMillis.h>

elapsedMillis timeElapsed;

//Patillas
const byte ledPinOUT     = 9;      // PIN6 --> Patilla 5 del Attiny, es el que tendrá asignada la salida de luz regulable y es un pin PWM
const byte ledPinROJO    = 6;      // PIN7 --> Patilla 6 del Attiny,
const byte botonOFF      = 2;      // PIN0 the number of the pushbutton pin
const byte botonSumaPin  = 3 ;     // PIN1 --> Patilla 2 del Attiny , es el boton que sumara (1 en este caso) al ciclo de trabajo subir luz
const byte botonRestaPin = 4;      // PIN2 --> Patilla 3 del Atinny , es el boton que restara (1 en este caso) al ciclo de trabajo bajar luz
     
// Variables
bool botonSumaValue;               // Variable para el boton de suma
bool botonRestaValue;              // Variable para el boton de resta
byte cicloTrabajo;                 // Variable para el ciclo de trabajo del led

// retraso en milisegundos entre parpadeos del LED
unsigned int interval = 50;

// estado del LED = LOW está apagado, HIGH está encendido
boolean ledState = LOW;
volatile int i = 0; // inicializando un entero para incrementar y disminuir la relación de trabajo.


//inicialización
void setup(){
    pinMode(ledPinOUT, OUTPUT);
    pinMode(ledPinROJO, OUTPUT);
    pinMode(botonSumaPin, INPUT);
    pinMode(botonRestaPin, INPUT);
    pinMode(botonOFF, INPUT);
}

void loop (){
    botonSumaValue  = digitalRead(botonSumaPin);
    botonRestaValue = digitalRead(botonRestaPin);
   
    if (botonSumaValue == HIGH) {
        if (cicloTrabajo++ < 254){
            cicloTrabajo = 255;
        }
        else {
            if (timeElapsed > interval) {
                ledState = !ledState;         // cambiar el estado de ALTO a BAJO a ALTO a BAJO ...
                digitalWrite(ledPinROJO, ledState);
                timeElapsed = 0;            // restablecer el contador a 0 para que el conteo comience de nuevo ...
            }
        }
    }

    if (botonRestaValue == HIGH)
       if (cicloTrabajo-- >1){
        cicloTrabajo = 0;
    }
    analogWrite(ledPinOUT, cicloTrabajo);

    if (digitalRead(botonOFF) == HIGH )  {
        cicloTrabajo = 0;
    }
}

Mikms

Gracias Surbyte por tu respuesta. Tal como me lo pones los pulsadores trabajan solamente de pulsadores, enciende al pulsar y al soltar apaga el led sin más.

El problema tiene que ser como dices (y yo suponia que era algo de eso) de como si no se detuviera realmente a los 256 sino que subiera mucho más, pues si no lo llevo a tope no hace el fallo y funciona correctamente, o si lo llevo a tope pero bajo algo de luz con el boton de BAJAR y despues apago con APAGAR... funciona correctamente

Habria alguna forma de limitar que no suba de por ejemplo 250 aunque se siga pulsado?

surbyte

Ya te he respondido incluso con un código que no probé pero debería estar mas o menos correcto.

Mikms

Yo te respondí a aquella respuesta tuya (que en ese codigo los pulsadores solamente hacen de pulsadores etc), y de nuevo agradecido por tu respuesta y tu tiempo. Está ya más claro el problema, que es como dices y ahora a solucionarlo.

surbyte

Mas alla que me resondiste y te respondí, probaste el código modificado?

Mikms

Si, lo probe y te comenté que así solamente funcionan como pulsadores y nada más.
"Gracias Surbyte por tu respuesta. Tal como me lo pones los pulsadores trabajan solamente de pulsadores, enciende al pulsar y al soltar apaga el led sin más."

El resto de cambios también los probé y nada de nada, pero lo que si que está claro que el problema es eso... que realmente no se para a los 255 sino que continúa en una especie de bucle de subidas y bajadas aunque el puerto serial no lo marque, y según donde lo pares en ese momento reaccionará haciendo ese pico o no haciéndolo, y en caso de que no llegue al 255 no lo hace nunca.


Lo que estoy probando ahora es "engañarlo" con que una vez que llegue a 250 y si se sigue pulsando reste un numero determinado (con -6 me ha ido bastante bien dentro del problema), por lo que aunque siga subiendo el valor +1, a la vez y acto seguido también restará esos -6, con ello ahora es muy rara vez la que hace ese pico.

Otra de las opciones que también probé es a subir y bajar en vez de 1 en 1, de 5 e 5, con ello se nota mucho menos ese pico, ya que no arranca tan apagado para ir subiendo de 1 en 1, y aunque lo sigue haciendo se nota mucho menos, pero es que entonces me sube demasiado rápido la luz, pero bueno son opciones que se están probando para intentar solucionarlo, porque es realmente molesto.

Gracias.

Sereno

A mi se me está escapando algo, al margen de que tu código esté mejor o peor, cuando apagas, cicloTrabajo pasa a valer 0, entonces no entiendo el pk de ese pico, si indistintamente del punto en que lo apagues, siempre empezará desde 0.
Code: [Select]
if (digitalRead(botonOFF) == HIGH )

{
  cicloTrabajo=0;
  delay (10);
 
}


Podrías explicar el esquema del circuito que controla la lámpara???

Mikms

#11
Feb 18, 2020, 10:24 pm Last Edit: Feb 18, 2020, 10:26 pm by Mikms
Hola Sereno, es que lo curioso es eso, que por algun motivo de programación hace ese salto, es como estar todo apagado... pulsar para comenzar ciclo y lo primero que hace es un flash (encendido como al 20% y apagado muy rápido), y ahora empieza a funcionar como debe.

Pero si no se lleva al máximo subiendo la luminosidad, o si se lleva al máximo pulsando todo el tiempo que se quiera mantener aunque ya haya llegado al máximo y a continuación se pulsa en botón de bajar para restar luminosidad (aunque sea muy poca, pero baje algo) y ahora se pulsa apagar...en el siguiente ciclo funciona correctamente.

Solamente falla cuando se pasa del máximo, cuando llega a tope de brillo y se pulsa o se mantiene pulsado el botón de subir luminosidad, si se apaga ahora desde el boton de apagar, da igual cuando lo vuelvas a hacer funcionar que lo primero que hará es ese pico de luz antes de funcionar.

La instalación ahora mismo es un arduino nano, con los 3 botones con sus respectivas R10k Pull down, y los dos leds (uno verde que indica subir, y el otro rojo que indica que se ha llegado al máximo y que está apagada la luz con sus respectivas R 330 ohmios)... No hay nada más y así tambien lo hace, es como lo estoy probando ya, porque desmonté todo y lo puse básico para descartar opciones, por tanto descarto ya todo fallo posible de hardware y tiene que ser algo de programa, y además relacionado con que pasa de los 256 aunque no lo indique el puerto serie. 

surbyte

Porque volvemos a cosas que ya estan detectadas como erróneas?

Si se usa un entero para la variable cicloTrabajo y se supera 255, analogWrite() vivirá enviando por el pin un valor de 255 porque no tolera mas que eso. Hasta que se presione botonRestaValue y caiga por debajo de 255.

Mikms

bueno dejalo, ya yo lo soluciono de otra forma en dos partes y ya esta. Gracias de todas formas

surbyte

Entonces tema terminado?

Go Up