External PWM IC for arduino

I am looking for an IC which I can easily interface with the arduino to get a PWM (rectangle) signal with variable frequency and duty cycle.
preferable 1 Hz to 20 MHz and a duty cycle which can be changed by 0.1%
I will manage if the frequency range is lower but I need at leat 1khz to 5 Mhz frequency steps preferable in 1Hz increments or less.
In a perfect world the output voltage of the signal would be 5V.

The AD9833 would be perfect frequency wise but as far as i know only sqare wave signals are possible (triangle and sine aswell).

Has anyone an idea what chip i could use? Or is it possible to use the AD9833?


I found this on the internet.

Most, or all, You ask for is covered by Arduinos.
Frequency changes calls for register changes.

@ Railroader: 1Hz increments is not possible as far as I know. 0.1% duty cycle change is not possible.
If I remember correctly about 1 MHz is the highest frequency

I am not sure what the article about quare and triangle waves with OpAmps has to do with the generation of rectangle signals.

The utmost limits are likely not available, yes.
Often members have huge demands that often are not really needed.
If You really have a well specified, and motivated, project that needs what You ask for, then I'm out. Highly special circuits and design is needed. Too many years since I designed such stuff....

I don't think your project is practical. To get 0.1% changes in duty cycles you need 1000 or more steps per cycle. At 20 MHz you would need a 20 GHz clock. Clocking at microwave frequencies is pretty exotic.

1 Like

Oops. My bad. I understood the post wrong.

Perhaps its time to tell us exactly what you re trying to achieve, rather then how you hope to do it?

1 Like

What an excellent proposal! :face_with_raised_eyebrow:

1 Like

I want to have rectangle signal generator capable of switching transistors.
where I can set the on time from 0.1┬Ás to 400┬Ás in 0.1┬Ás steps
The signal should be controlled by an ┬ÁController over serial communication

This differs quite a lot from your demands in your first post.
What about the off time?

A 16 MHz Arduino can't easily do 1/10 microsecond intervals. Would 1/8th or 1/16th of a microsecond be usable? If you don't need accuracy in millis(), micros(), delay()... you could switch to a 20 MHz crystal to get 1/10th microsecond timing.

It should not be too difficult to adapt millis and micros to a 20MHz crystal. Maybe a new Entry in boards.txt is sufficent.

Or you could load the Minocore bootloader, which has support for 20 MHz crystal.

the off time should be between 0-100┬Ás
I guess i will try the 16th of a microsecond and call it close enough
I will test it tomorrow with the arduino and an oscilloscope.
Is there an easy way to change the frequency inside the programm?

what about the tlc5940 chip I just found it sounds about perfect.

If you mean this one why not post the link?

at a glance this device GENERATES PWM and the function of the arduino would be to tell it what to do over the serial interface. You would need to handle that yourself unless someone is aware of code or a library to do it as its not rs232 & ff standard.

I think we have been trying to find a way for an arduino-ish device to PRODUCE that pwm which seems not to be your intention.

The TLC5940 has a flexible serial interface, which can be connected to microcontrollers or digital signal processors in various ways. Only 3 pins are needed to input data into the device. The rising edge of SCLK signal shifts the data from the SIN pin to the internal register. After all data is clocked in, a high-level pulse of XLAT signal latches the serial data to the internal registers. The internal registers are level-triggered latches of XLAT signal. All data are clocked in with the MSB first. The length of serial data is 96 bit or 192 bit, depending on the programming mode.

An off time of 0 isn't really practical - it means simply a HIGH signal.
Assuming a minimum off time as the same as your min on time ( 0.1┬Ás ) means a max frequency of 5 MHz. And maximum on/off of 400/100┬Ás means a lowest frequency of 2kHz.
If you change the system frequency of the ATMega to 20Mhz, this can easily be done by e.g. timer 1 of the Arduino.
If you leave the clock at 16MHz you have the choice of all times beeing 20% longer, or having a resolution of 0.0625┬Ás instead of 0.1┬Ás. The lowest possible frequency in this case is about 244Hz.
But it's really a lot different to your first demands.

Now we're getting close to a specification that can be implemented. The maximum cycle time is 500┬Ás. At 16 ticks per ┬Ás that's 8000 ticks, well within the capability of Timer1 (65536 ticks).

void setup()

  pinMode(10, OUTPUT); // OC1B pin
  TCCR1A = 0;
  TCCR1B = 0;

  // Set WGM15: FastPWM, OCR1A is TOP
  TCCR1A |= _BV(WGM11) | _BV(WGM10);
  TCCR1B |= _BV(WGM13) | _BV(WGM12);

  // Enable FastPWM on OC1B (Pin 10)
  TCCR1A |= _BV(COM1B1);

  OCR1A = 7999; // 500 microseconds (8000 ticks) cycle time
  OCR1B = 6400; // 400 microseconds (6400 ticks) on time

  // Start the timer running with a prescale of 1
  TCCR1B |= _BV(CS10);

void loop()
  unsigned TotalTicks;
  if (Serial.available())
    unsigned highTicks = Serial.parseInt();
    unsigned lowTicks = Serial.parseInt();
    if (highTicks != 0 && lowTicks != 0)
      TotalTicks = highTicks + lowTicks;
      OCR1A = TotalTicks - 1;  // TOP
      OCR1B = highTicks;