Frecuencia máxima del PWM

Hola, soy nuevo en el foro y espero poner esto en el sitio correcto.

Os comento un poco por encima lo que estoy haciendo: estoy trabajando en mi proyecto de final de grado con una placa Arduino Mega ADK para realizar el control y regulación de un convertidor Buck. He estado mirando información por internet y he visto que la máxima frecuencia que puedo conseguir es de 62.5kHz. Así que programe el arduino para conseguir esa frecuencia, usé el siguiente código:

     digitalWrite(C, HIGH);  
     delay(0,000016);          
     digitalWrite(C, LOW);  
     delay(0,000016);

Siendo C el pin de salida digital PWM 6.

Al representar la señal en el osciloscopio vi que en lugar de una señal de onda cuadrada como esperaba, el flanco de subida lo hacía bastante bien y rápido pero al hacer el flanco de bajada me hacía una curva exponencial, como si se estuviera descargando un condensador por ejemplo.

A ver si alguien me puede ayudar a cómo obtener la señal a 60 kHz por ejemplo, ya que para el correcto funcionamiento del convertidor y no tener un convertidor muy grande en tamaño, cuanta más frecuencia obtenga del arduino mejor.

Un saludo y gracias,

Sergio Alonso.

Pin 6 es gobernado por el timer4; al ser de 16 bits jamás lograrías tal frecuencia.

Te recomiendo entonces usar el pin 9 o 10, los cuales son gobernados por el timer2; es de 8 bits así que sí se logra tal frecuencia.

Agrega esta línea en el setup:

TCCR2B = TCCR2B & 0b11111000 | 0x01;

Ahora sí sería no más de usar analogWrite normalmente.

PD: no recomiendo el timer0 porque afecta a delay y millis.

Hola

El grado de control que quieres es dificil desde el lenguaje del Arduino, hay que manejar directamente los timers, y ademas definir su modo de trabajo en no pwm es ecir en CTC (jerga del atmega).

En primer lugar no se puede ir mas allá de 980 Hz Arduino analogWrite() en modo PWM.

En segundo lugar:

     digitalWrite(C, HIGH); 
     // ... esto es un error de sintaxis y de concepto
     delay(0,000016);         
     digitalWrite(C, LOW); 
     // ... esto es un error de sintaxis y de concepto
     delay(0,000016);

     // ... esto es lo estandar:
     // delay(unsigned long milisegundos);
     // ... Siendo milisegundos el valor deseado

Aqui tienes la sintaxis correcta: Arduino referencia del lenguaje

Una solucion seria cambiar ese delay() a delayMicroseconds(16) puesto que tu buscas alrededor de 60 kHz de frecuencia.

Hasta aqui todo bien, pero cuando nos movemos en esos tiempos, el tiempo que consume el software para ejecutarse tambien cuenta y mucho, por lo que quizas tuvieses que usar un delay mas pequeño.

Mi consejo es comienzar sin delay y medir con el osciloscopio la señal. Luego segun la veas puedes ir introduciendo valores en aumento (de 1 useg en adelante), y a ver hasta donde llegas. Algo así:

     digitalWrite(C, HIGH); 
     delayMicrosegundos(1);  // Valor experimental
     digitalWrite(C, LOW); 
     delayMicrosegundos(1);  // Valor experimental

Si se quiere un control real sobre los tiempos y señales generados por el ATmega2560 hay que bajar de lenguaje y programarlo en assembler (aunque sea desde C++).

Saludos.

Prueba con esta librería Arduino PWM Frequency Library V-05

Acá tienes como usarla PWM Frequency Library

Lucario448: Pin 6 es gobernado por el timer4; al ser de 16 bits jamás lograrías tal frecuencia.

Te recomiendo entonces usar el pin 9 o 10, los cuales son gobernados por el timer2; es de 8 bits así que sí se logra tal frecuencia.

Agrega esta línea en el setup:

TCCR2B = TCCR2B & 0b11111000 | 0x01;

Ahora sí sería no más de usar analogWrite normalmente.

PD: no recomiendo el timer0 porque afecta a delay y millis.

Hola, he utilizado el comando analogWrite y consigo una frecuencia de 31.1 kHz que es bastante aceptable y además consigo variar el ciclo de trabajo de la señal bastante bien. ¿Se podría aumentar esa frecuencia?

Un saludo!

Edito:Para leer con el analogRead ¿tendré algún problema de velocidad también? es decir, ¿puedo fijar a que frecuencia y en que momento quiero que lea el valor deseado?

Edito:Para leer con el analogRead ¿tendré algún problema de velocidad también? es decir, ¿puedo fijar a que frecuencia y en que momento quiero que lea el valor deseado?

Que quieres leer?

surbyte: Que quieres leer?

A ver en principio quiero detectar cuando empieza a conducir un diodo LED, ya que es el objetivo del proyecto. Había pensado colocar una pequeña resistencia en serie con el LED y medir su tensión, de esta manera en cuanto tenga algo de tensión ya estará conduciendo.

A ver en principio quiero detectar cuando empieza a conducir un diodo LED

Yo creo que no te estas explicando bien y te diré porqué: Recuerda que nosostros no estamos en tu proyecto, no lo conocemos, no has mostrado nada de el, de modo que solo nos podemos basar en lo que has escrito. Solo has dicho hasta ahora, que harás un proyecto de fin de grado, y que se trata de un convertidor BULK usando un MEGA ADK. Hasta ahi bien! Tu primer problema era la frecuencia de trabajo del DC-DC que por limitación o por lo que sea, has establecido en 31khz. Ahora consultas por detectar cuando conduce un LED pero no dices que lo pone a conducir? Lo pone a conducir tu código, lo pone a conducir el DC DC ?

Debes ser algo mas descriptivo porque repito, no podemos visualizar cual es tu objetivo.

srgalonso: Hola, he utilizado el comando analogWrite y consigo una frecuencia de 31.1 kHz que es bastante aceptable y además consigo variar el ciclo de trabajo de la señal bastante bien. ¿Se podría aumentar esa frecuencia?

Aparte de la línea que te dije que agregaras, agrega esta también:

TCCR2A |= _BV(WGM21) | _BV(WGM20);

Creo que te merece la pena probar la libreria que menciono surbyte:

surbyte: Prueba con esta librería Arduino PWM Frequency Library V-05

Acá tienes como usarla PWM Frequency Library

La he ojeado con detenimiento y puede subir a 2 MHz, y quizás mas. Por lo tanto el tema de la velocidad lo tendrias ampliamente resuelto.

Para el ATmega2560, el datasheet dice:

  1. ADC – Analog to Digital Converter 26.1 Features • 10-bit Resolution • 1 LSB Integral Non-linearity • ±2 LSB Absolute Accuracy • 13μs - 260μs Conversion TimeUp to 76.9kSPS (Up to 15kSPS at Maximum Resolution) • 16 Multiplexed Single Ended Input Channels • 14 Differential input channels • 4 Differential Input Channels with Optional Gain of 10× and 200× • Optional Left Adjustment for ADC Result Readout • 0V - VCC ADC Input Voltage Range • 2.7V - VCC Differential ADC Voltage Range • Selectable 2.56V or 1.1V ADC Reference Voltage • Free Running or Single Conversion Mode • Interrupt on ADC Conversion Complete • Sleep Mode Noise Canceler

por lo que tu digitalRead() queda definido también (hasta 76900 muestras por segundo maximo).

surbyte: Yo creo que no te estas explicando bien y te diré porqué: Recuerda que nosostros no estamos en tu proyecto, no lo conocemos, no has mostrado nada de el, de modo que solo nos podemos basar en lo que has escrito. Solo has dicho hasta ahora, que harás un proyecto de fin de grado, y que se trata de un convertidor BULK usando un MEGA ADK. Hasta ahi bien! Tu primer problema era la frecuencia de trabajo del DC-DC que por limitación o por lo que sea, has establecido en 31khz. Ahora consultas por detectar cuando conduce un LED pero no dices que lo pone a conducir? Lo pone a conducir tu código, lo pone a conducir el DC DC ?

Debes ser algo mas descriptivo porque repito, no podemos visualizar cual es tu objetivo.

Vale lo intento explicar mejor.

La idea principal es realizar el driver de una lámpara LED. Por lo que para que este driver valga para cualquier lámpara LED que le enchufemos, quiero realizar un encendido suave, es decir, quiero aumentar el ciclo de trabajo del convertidor hasta conseguir que por el sensor que ponga en la salida tenga algo de corriente. Por lo que mi idea es, aumentar el ciclo de trabajo y leer, e ir realizando eso en cíclicamente hasta que empiece a conducir, y una vez que el haya comenzado a conducir ya que empiece a actuar el regulador que tengo que programar en el Arduino.

Alfaville: Creo que te merece la pena probar la libreria que menciono surbyte: La he ojeado con detenimiento y puede subir a 2 MHz, y quizás mas. Por lo tanto el tema de la velocidad lo tendrias ampliamente resuelto.

En cuanto tenga tiempo de pasarme por el laboratorio le hecho un vistazo a ver si funciona y os comento.

srgalonso: Por lo que mi idea es, aumentar el ciclo de trabajo y leer, e ir realizando eso en cíclicamente hasta que empiece a conducir, y una vez que el haya comenzado a conducir ya que empiece a actuar el regulador que tengo que programar en el Arduino.

Entiendo, primero determinar la caída de voltaje del LED (voltaje mínimo necesario para que por este circule corriente); y luego... seguir incrementando hasta alcanzar el voltaje máximo (modo CV) o amperaje máximo (modo CC)?

De ser así, te sigo; porque antes tenía en mente un proyecto similar, solo sin saber por donde empezar. Ni siquiera tengo idea qué inductor utilizar, o cuál diodo schottky...

Ves que comenzamos a sintonizar contigo!!

De todos modos, porque no pones un esquema asi vemos mejor todo el panorama.

Lucario448: seguir incrementando hasta alcanzar el voltaje máximo (modo CV) o amperaje máximo (modo CC)?

Lo que quiero es crear un regulador que regule la corriente frente al ciclo de trabajo y que una vez que el diodo haya comenzado a conducir, que este regulador empiece a trabajar y ya si todo funciona bien intentaré modificar la corriente de referencia que le meta al regulador desde un movil a través de Android.

surbyte: porque no pones un esquema asi vemos mejor todo el panorama.

Dejame prepararlo a ver si así os lo aclaro mejor.