PWM help!

Hi everyone,

I have been looking up online and trying to have an output as the bottom picture in my attachments.
Can anyone guide me through how I can tackle the problem? Thanks!


So 20Hz (cause I don't know hz) PWM with variable duty cycle?

Start by making a 20Hz PWM signal. I would say millis() is perfectly fine for something that slow.

Next, although it gives a sample-and-hold aspect, instead of a fixed on period I would simply sample (analogRead() ) the signal the moment you make the output high and use that (after doing the math) as the on time.

Alternatively you could make a 20 Hz "saw tooth" (aka, increment a variable from 0 to max in 1/20 second) and sample the input all the time and compare it to the "saw tooth". That's a bit more correct for what you show but will take a lot more process power from the Arduino.

Image from Original Post so we don’t have to download it. See this Image Guide



How can I make a 20Hz PWM signal?

Have a look at the blink without delay example in the IDE.

For 20Hz, forget about timers, see:

I would say millis() is perfectly fine for something that slow.

A good staring point for using millis() is blink without delay.

And for the second step, I assumed the sinus came from an external source. Then can you tell us where the ±2Hz red signal and 20Hz yellow signal come from?

But what exactly do you want? Which of the signals?

The bottom one? That's just a 20Hz PWM modulated with a 2Hz sine. So only that? No input?

If you have a input signal (I guess the red?) then what I said in replay #3 still holds. Sample that input signal and determine the on length of the PWM.

But you might want to switch to micros() instead of millis because 20Hz = 50ms. So timing that with ms will only give a resolution of 50.

You could also do it with a counter and interrupts. It's a bit more precise but it's s lot more work and more complicated.


Sample that input signal and determine the on length of the PWM.
But you might want to switch to micros() instead of millis because 20Hz = 50ms.

Here’s a simple approach that may work if the pwm values at 20Hz can be created with a higher frequency pwm. I’m not sure how the input to the LRA driver works. If each pulse needs to be a created with a digitalWrite with a varying total on/off time = 50 ms than this approach is probably not correct.

/******** Sine wave parameters ********/
#define PI4     4*3.14159 // 2 sine wave cycles
#define AMP     127     // PWM Multiplication factor for the sine wave
#define OFFSET  128   // Offset shifts wave to just positive values

/******** Lookup table ********/
#define LENGTH 20 // The length of the waveform lookup table
byte wave[LENGTH]; // waveform values for PWM

const byte pulsePin = 9;

void setup() {
  pinMode(pulsePin, OUTPUT);

  /******** Populate the waveform lookup table ********/
  for (byte i = 0; i < LENGTH; i++)
    float v = (AMP * sin(((PI4 / LENGTH) * i)));
    wave[i] = byte(v + OFFSET);  // Store value as integer


void loop() {
  static unsigned long lastPulseTime;
  static byte i = 0;
  if (micros() - lastPulseTime >= 50000ul) //20Hz
    lastPulseTime += 50000ul;
    analogWrite(pulsePin, wave[i]);
   // Serial.println(wave[i]);
    if (i == LENGTH - 1)
      i = 0;

OK. Is this correct.

You have a varying analog input from a pressure sensor.
You want to map that value to a duty cycle 0>100%.
You want to output a 20Hz PWM with that duty cycle.

The output is used as an input to a controller/driver chip for a linear resonance actuator.

Can you provide a link to the chip you are using. 20Hz as an input frequency seems low.

Huh, now you want to modulate the frequency? Where/how do you get/ why do you want different frequencies?

Smells to me like a XY-problem. Can you please give us a FULL project description?

The project is about getting haptic feedback from the measurement of pressure sensor. The haptic feedback is given by a Linear Resonant Actuator(LRA). The analogue output from the pressure sensor will be feed into the Arduino and Arduino has to produce a PWM (the bottom graph of the first post) to the driver circuit and the driver circuit will produce an ac current to the Linear Resonant Actuator. The different frequencies are determined by the resonant frequency of a particular LRA so when it is at the resonant frequency, the LRA is at its highest effect. The analogue signal from the pressure will be divided into 4 levels and that gives information of which PWM to feed into the driver circuit.

I think I understand.

You want to change the pwm frequency going into the driver. The pot setting will determine the frequency. How does the input frequency relate to the output frequency to the LRA. I ask, because the resonant frequency of the devices I see are much higher than 20Hz or 30Hz. Can you provide links to the LRA you are using?

In the bottom graph of the first post you show the duty cycle a 20Hz PWM signal being modulated by a 2Hz sinewave, but in later posts you indicated that there is no sine wave. Is there going to be any variation in the duty cycle?

Im curious to know how the input signals frequency and duty cycle relate to the haptic output. If you want to produce a click or a buzz how do you know what to do?

You may want to take a look at the TimerOne library. GitHub - PaulStoffregen/TimerOne: TimerOne Library with optimization and expanded hardware support
It has a very easy to use PWM function which can be set for your low frequencies. The duty cycle can be easily varied, and it has 10 bit resolution of the duty cycle.

The PWMs that I need is at 205Hz(matching the resonant frequency of the LRA) and that has to be modulated with a sine wave at 20/40/50Hz. So the higher the sine wave frequency modulating with the PWM signal, the LRA will vibrate faster/harder.

Thank you. This bears little similarity with the questions you have been asking and the initial information presented in this thread.

If you had asked "How do I generate a 205Hz pwm signal with duty cycle modulation matching a sine wave at 20/40/50 Hz. " you would have had an answer by now.

Do yo know how to achieve what you want?

If you need additional assistance, please post your code pasted within the code tags found at </> in the tool bar so that it appears in a scrolling window.

As I understand it, the DRV 8601 is a driver. Does the actual LRA it is driving have a different part number and manufacturer, or is is a TI part with the same number?

Thanks for the quick reply, cattledog.

Apologies to the confusion. I only have a rough idea of making use of sine wave library and producing the PWM by analogwrite(). Also, I read about how timers and counters might work? Can you please give me some guidances on how to achieve the desired signal?

I am sorry that I have been giving the wrong website for the LRAs. Here are the potential ones that I am going to use (file:///C:/Users/Asus/Downloads/C08-001-datasheet-R0V6.pdf,,

I do not think you are going to be able to modulate your 205Hz pwm output with 20/40/50Hz sine waves with any reasonable resolution because the output frequency is too low and the sine wave frequencies are too close.

You can only output 205 values per second. Most sine wave digitization is at least 8 bits with a lookup table of 256 values. For an 8 bit representation of 20Hz sine wave you need to output 20x256 = 5120 values in a second. Clearly at 205Hz you can not get to all the values in the table in one second and can only output 205 of the 5120. At 40Hz and 50Hz you sample even less of the values required (40x256 =10240 or 50x256= 12800)in a second.

I believe that this undersampling can be handled with DDS (direct digital synthesis) techniques KO7M - Ham Radio Blog: Direct Digital Synthesis (DDS)
but this is fairly complex. I think, for example, that with the case of 205Hz trying to get through 5120 samples you ouput every 20th value in the sine table and step through with different starting points each pass. Whether or not synthesizing a complete sine wave with this proceedure is useful for an LRA and its driver is unknown.

If you try to digitize the sine wave with a resolution suitable for the 205Hz there is very poor resolution.

I don’t know your application, but there is a different driver (DRV2605) with multiple built in drive waveforms for different haptic effect. You might want to think about getting one of these modules which has that chip.Overview | Adafruit DRV2605L Haptic Controller Breakout | Adafruit Learning System