Cómo aumentar el rango de atenuación del LED controlado por mosfet

Poco a poco me estoy metiendo en los circuitos y armé un atenuador LED PWM. El led es impulsado por este circuito:

ingrese la descripción de la imagen aquí

Estoy manejando el PWM a través de un dispositivo BLE separado que asigna una entrada de usuario de [0, 100] a un valor de 8 bits para el PWM de arduinos [0, 255]. Aquí está el código:

int led = 9;           // the PWM pin the LED is attached to
int intR;
int t;

void setup() {
  Serial.begin(9600);
  Serial.println("serial connected...");

  // declare pin 9 to be an output:
  pinMode(led, OUTPUT);

  analogWrite(led, 0);
}

void loop() {
  if (Serial.available() > 0) {
    intR = Serial.parseInt();
    t = map(intR, 0, 100, 0, 255); //remaps intR from [0, 100] -> [0, 255] to scale to PWM
    Serial.print(intR);
    Serial.print(" -> ");
    Serial.print(t);
    Serial.println("");  

    analogWrite(led, t);
  }
}

Cada vez que configuro el valor de atenuación en 100 (100 % del ciclo de trabajo), el LED brilla con bastante intensidad, pero cuando configuro el valor en 0, el LED brilla probablemente con un brillo del 60 %.

¿Qué tendría que hacer para hacer una transición suave del LED de un estado completamente APAGADO a un estado completamente ENCENDIDO?

EDITAR:

Después de una discusión en los comentarios, actualicé mi código y circuito y algo parece estar mal. El siguiente código y el par esquemático me brindan el mejor rango de atenuación (visualmente, tal vez 10-100% de salida total) y funciona en múltiples mosfets de mi paquete.

Nuevo código y esquema del circuito:

int led = 9; // the PWM pin the LED is attached to
int intR;

void setup() {
  Serial.begin(9600);
  Serial.println("serial connected...");

  // declare pin 9 to be an output:
  pinMode(led, OUTPUT);

  digitalWrite(led, LOW);
}

void loop() {
  if (Serial.available() > 0) {
    intR = Serial.parseInt(); //reads the next valid integer
    Serial.print(intR);
    Serial.println("");

    if (intR <= 255 && intR >= 0) {    
      if (intR == 0) {
        digitalWrite(led, LOW);
      } else {
        analogWrite(led, intR);
      }
    }
  }
}

Esto funciona

Mis MOSFET están etiquetados como P30N06LE, que corresponden a esta hoja de datos RFP30N06LE . Y a menos que mis fetos se hayan hecho incorrectamente, mi drenaje realmente va directamente a GND, y mi LED negativo se alimenta a la fuente. El problema que tengo ahora es doble: 1) comprender por qué mi circuito funciona de esta manera y 2) lograr que mi LED se apague por completo al configurar el pin en BAJO.

Con la configuración anterior, cuando el pin 9 está configurado en BAJO, el LED tiene un brillo de ~ 10%, y cuando retiro físicamente el cable del pin 9 de arduino, el LED se apaga por completo. Si luego conecto el cable en varios pines sin alimentación, el LED brilla con un brillo bajo, lo que indica que hay suficiente voltaje para alimentar el fet. ¿Cómo puedo hacer que el led se apague por completo?

¿Qué MOSFET estás usando?
Estoy usando un P30N06LE
¿Qué tan rápido está enviando datos en serie a su MCU? Además, ¿está enviando esos datos como una rampa (como en un diente de sierra?) ¿O está enviando el valor 0 y manteniéndolo allí (sin cambiar el valor) y aún viendo el LED en aproximadamente 60%?
¿Puede el LED tomar los 12 voltios completos?
¿Estás seguro de haber conectado correctamente el MOSFET? El LED debe estar conectado al pin central.
@τεκ Correcto, mi LED está conectado al pin central (drenaje) del mosfet. El PWM está conectado a la puerta y el pin de fuente está conectado a tierra.
@jonk Edité mi código para establecer el valor en un ciclo de trabajo del 0% en la inicialización, todavía tiene un brillo casi total.
@GregoryNeal Retire la conexión del pin de E / S, pero deje la resistencia de 1k a tierra. Si eso no apaga el sistema de 9 LED, el problema NO está relacionado con la disposición de los pines de E/S. es otra cosa Si eso apaga el LED, entonces tienes un problema con tu pin de E/S (¿salida analógica?). (Supongo que se supone que la luz de su techo funciona con 12 V).
@jonk Cuando saco el pin de E / S, deja la luz encendida, entonces, ¿la configuración de mi circuito es incorrecta? ¿Hay alguna forma de saber con certeza si mi LED requiere 12 V? No pude encontrar ninguna hoja de especificaciones en línea
@GregoryNeal Creo que sí. Tiene 9 LED y supuestamente está diseñado para aplicaciones automotrices de 12 V. Simplemente puede conectarlo directamente a la batería de 12 V. Pero creo que se iluminará bien, si lo haces. Así que probablemente haya conectado mal las cosas o tenga un NFET defectuoso. Probablemente esté mal conectado (verifique las asignaciones de pines CUIDADOSAMENTE). ¡Asegúrese de saber qué pines son cuáles en el NFET! Y también verifique las polaridades de su voltaje.
@jonk De acuerdo con esta hoja de datos: sparkfun.com/datasheets/Components/General/RFP30N06LE.pdf Mi configuración original tenía el LED negativo en el pin central, que figura como drenaje. Y el resto como: - LED -> Drain GND -> Source PWM -> Gate Una vez que cambié las entradas de drenaje y fuente para que: GND -> Drain -LED -> Source PWM -> Gate El rango de atenuación aumentó dramáticamente (casi a un rango utilizable). Sin embargo, cuando desconecto el pin PWM, ahora salta al estado completamente ENCENDIDO en lugar de cortar el flujo de corriente como esperaría.
@GregoryNeal Bueno, casi parece que tienes un PFET, no un NFET. Pero eso tampoco se ajusta a su descripción en todos los detalles. Muy extraño. Creo que debe volver a algunas pruebas muy básicas del FET. Use una resistencia en el pasador de drenaje, en lugar de la luz LED. Mida la caída de voltaje a través de la resistencia para dos casos: puerta con conexión a tierra y un par de resistencias divisoras de voltaje a la puerta que deberían producir aproximadamente 3 V a la puerta. Hay algo mal.
@jonk usando esta configuración de compuerta conectada a tierra y midiendo el voltaje en R1 obtengo -11.6V. Y cuando reemplazo la puerta conectada a tierra con una fuente de ~3.3V como en esta configuración , el voltaje en R1 es -12.1V.
Tienes el terminal de 12V - (negro) conectado al GND de Arduino, ¿correcto? Y el terminal 12V + (rojo) conectado al LED.
@τεκ Sí, así es como está configurado. Hasta ahora he descubierto que construir el circuito de esta manera tiene los mejores resultados. Establecer el PWM en 0 da como resultado un brillo de aproximadamente 10-20% en el LED, y establecer el PWM en 255 da como resultado un brillo aproximadamente completo. Estoy pensando que mi mosfet es malo, pero no sé qué pruebas ejecutar en él.

Respuestas (2)

¿Cómo estás convirtiendo 0-100 a 0-255? Parece que estás usando la función de mapa externo . Todo se explicaría si la mapfunción estuviera "funcionando mal" y devolviendo 155-255 para una entrada de 0-100. Dado que 155 es el 60% de 255. Tal vez esa función no funcione de la manera que crees que funciona.

¿Por qué no simplemente ir?t = intR * 255 / 100?

De hecho, ¿por qué incluso ingresar una escala de 0-100, pensar en binario e ingresar una escala de 0-255?

Edité mi código para eliminar la función de mapa, sin embargo, el comportamiento sigue siendo el mismo. ingresar 255 parece ser el brillo total, pero ingresar 0 sigue siendo un brillo casi total, solo un poco más tenue. el código:void loop() { if (Serial.available() > 0) { intR = Serial.parseInt(); //reads the next valid integer Serial.print(intR); Serial.println(""); if (intR <= 255 && intR >= 0) { analogWrite(led, intR); } } }
¿Qué número es la decodificación de Arduino? ¿Alguna forma de decir eso? ¿Funciona si envías un número 0 al Arduino directamente? ¿Qué pasa si envías 1?
Tengo un módulo HM10 BLE conectado al arduino. Estoy usando el escáner BLE de la aplicación de Android (para probar). Una vez que me conecto, envío una solicitud de escritura a la característica personalizada del HM10. El arduino lee los bits y analiza el número entero y luego envía los datos directamente al pin PWM. Enviar un valor de 0 lo establece en un estado bastante brillante. Luego, establecerlo en 1 después aparentemente no hace nada. No puede ver la diferencia en la salida de luz a menos que tenga un delta de alrededor de 60 o 70.

Para solucionar problemas, quitaría de la ecuación el valor de serie recibido. solo configurat = 0;

Esto es lo que sospecho que puede estar pasando.

Esta respuesta requirió demasiadas suposiciones porque los valores recibidos no fueron explicados. Pero es una posibilidad si el MOSFET funciona correctamente.

Tengo un módulo HM10 BLE conectado al arduino. Estoy usando el escáner BLE de la aplicación de Android (para probar). Una vez que me conecto, envío una solicitud de escritura a la característica personalizada del HM10. El arduino lee los bits y analiza el número entero y luego envía los datos directamente al pin PWM.

Si entiendo correctamente, está utilizando un solo carácter ASCII serial para sus valores PWM.

Lo que no explicas es los posibles valores que se reciben en el puerto serie.

Un cero, en ASCII, sería un carácter NULL. Donde un "0" sería 32 y 100 sería "d". Suponiendo que está utilizando valores ASCII de 7 caracteres y esa es la razón por la que está utilizando valores de nivel de atenuación de 0-100.

Eso tendría sentido que en realidad esté enviando un "0" (valor de 32) en lugar de NULL (valor cero). Tu ojo podría malinterpretar fácilmente la diferencia entre el 32 % y el 60 % de intensidad luminosa.



No entiendo por qué analogWrite(led, t);está dentro del
if (Serial.available() > 0){}.
Solo podía enviar un solo carácter para cambiar el nivel de atenuación si
analogWrite(led, t);
no estaba entre ifcorchetes.
Creo que estás enviando innecesariamente un flujo continuo de caracteres.


He revisado mi código y puedes verlo en mi edición. En la aplicación de escáner BLE, tengo la opción de enviar texto o matrices de bytes. He estado enviando valores de texto de 0 a 255, que supongo que la función de arduino ha analizado correctamente Serial.parseInt. ¿Las bibliotecas de arduino no analizan correctamente el valor de texto recibido de un dispositivo ble?
Cuando recibe un ASCII "0", el valor del entero es 32. Cuando imprime un entero con un valor de 32, probablemente recibirá un ASCII "0". Esto puede hacerle pensar que el valor de intR es cero cuando en realidad es 32. No estoy familiarizado con las bibliotecas de Arduino. Por lo general, con C, para enviar un carácter ASCII cero, puede "imprimir" 32 o "0". Está enviando un valor entero que el compilador puede convertir el entero en su carácter ASCII. No he escrito ningún código Atmel en los últimos 20 años. Escribí principalmente en ensamblador y cuando escribí en C, usé IAR Systems Embeded Workbwench
De acuerdo con este tutorial de arduino y mi referencia a la documentación , Serial.parseInt()lee el valor ASCII del búfer de flujo y lo analiza en el entero lógico y no en el valor ordinal. Si el búfer contenía "5,220,70", entonces la primera llamada a Serial.parseInt()devolverá el número entero 5, la segunda llamada devolverá 220. En mi código actualizado no estoy enviando ningún valor separado por comas, por lo que la única llamada a Serial.parseInt()debería devolver el valor correcto valor.
Debería intentar tomar analogWrite (led, intR); fuera de la sentencia if. analogWrite debe ejecutarse en cada iteración del ciclo. Solo está ejecutando analogWrite cuando se reciben datos en serie. Recomiendo encarecidamente tratar de usar un valor de cero para intR y no usar los datos recibidos para establecer el valor de intR o cambiar analogWrite a analogWrite (led, 0);