Sin wave output with PWM pin output amplitude question

Hey Everyone,

Disclaimer: first post, please advise if I am failing community guidelines.

This topic has been all but beaten into the ground. I "wrote" (more like took from other posts on this topic) a simple lookup table and analogWrite to a PWM pin on my AT Mega. Then I put it through a RLC low pass filter (R=10000 ohm, L = 10mH, C = 10uF) to get a sin wave. I used parts I had laying around. When you change the size of the look up table or the delay period, you affect the frequency of the output sin wave (after the lowpass filter). That all makes sense and is clearly discussed in this thread. However when you increase the frequency, you decrease the output peak voltage. I am pretty sure that that is due to the constraints of the PWM pin, but I was hoping someone could explain it to me because I am failing to understand what constraints on the PWM pin cause this. So the question is: why does amplitude decay as frequency is increased?

const byte sig[] = {
128,143,159,174,189,202,215,226,
235,243,249,253,255,255,253,249,
243,235,226,215,202,189,174,159,
143,128,112,96,81,66,53,40,
29,20,12,6,2,0,0,2,
6,12,20,29,40,53,66,81,
96,112
};

void setup() {
  pinMode(6, OUTPUT);
}

void loop(){
  for(int i = 0; i<50; i++)
  {
    analogWrite(6,sig[i]);
    delay (20); 
  }
}

The amplitude will decrease if the sine wave (PWM) frequency goes above the roll-off frequency of the RLC low pass filter.

What is the roll-off frequency and what frequencies are you generating? Post a schematic of the filter you made.

why does amplitude decay as frequency is increased

There is nothing in the posted code that changes any frequency. It outputs 50 steps approximating one cycle of a sine wave every second, so that is 1 Hz.

1 Like

you are correct. I should have posted both codes. I am manually changing the delay value between tests.

This is my schematic:
![Screenshot 2024-01-18 142457|314x101]
(upload://5IuhWPenycP8IXtbCJuBTV7CCxw.png)

I used this website for the RLC calculation for simplicity: RLC Low-Pass Filter Design Tool

R = 10000 Ohms
L = 10mH
C = 10uF

the first code is posted, but this is the first code:

const byte sig[] = {
128,143,159,174,189,202,215,226,
235,243,249,253,255,255,253,249,
243,235,226,215,202,189,174,159,
143,128,112,96,81,66,53,40,
29,20,12,6,2,0,0,2,
6,12,20,29,40,53,66,81,
96,112
};

void setup() {
  pinMode(6, OUTPUT);
}

void loop(){
  for(int i = 0; i<50; i++)
  {
    analogWrite(6,sig[i]);
    delay (20); 
  }
}

The second code is the same, but I changed "delay (20)" to "delay(1)" which should increase the frequency from 1Hz to 20Hz if I am understanding correctly. When I do that, peak voltage decays from approximately 1.15V peak to approximately 0.20V peak.

Why did you choose those values? Can you show your calculations for the filter?
If I ignore the inductor I see a low pass filter with a cut-off frequency of 1.6Hz.
The inductor would seem to have very litle effect as XL at 1.6Hz is only 0.1 ohm

Can you post a schematic?

oh boy, that is frustrating, When I try to upload the image according to the tutorial, this is what happens:

Screenshot 2024-01-18 142457

I chose those values because it is what i had lying around and it gave me a cutoff frequency of 503hz. I am playing around with low frequency signals less than 200Hz.

You need to filter the unwanted harmonic - NOT th efrequency you want to use!

I think there must be an error in the website calculator.

That is the expected result. According to this simulation, the amplitude is down 20dB at 20 Hz (a factor of 10 in voltage). That agrees with the Bode plot on the web calculator, too.

I don't know how the "cutoff frequency" is defined on the web site, but the "3dB" rolloff is about 1.5 Hz.

For cleaning up a stepped sine wave at a few Hz, a 1K/1uF RC filter should be fine.

Oh ok great! That is super helpful. I will do my calculations manually from now on. I guess that is what I get for not double checking my own circuit calcs. Thank you guys for the quick response.

I feel so stupid now. I just swapped out my resistor for a 10 ohm and it went to work like a champ. :man_facepalming: Thanks again guys.

I think you will fry your ouput pin with that low value resistor..

1 Like

What are you expecting to drive from the signal? The filter calcs assume there is nothing further connected!
Also you should probabaly lose the inductor and go for a simple RC filter with r appropriate to the PWM output. eg upwards of 200 ohm.

Then you may need to buffer the output to suit your load.

Finally, the frequency of the harmonic (Fh) will be N times the fundamental (F0) where N is the number of sample points. So to get good separation between F0 and Fh you should generate upwards of 100 samples per wave.

1 Like

@build_1971 - you are right, I should have looked at the outputs available current. Thankfully I didn't fry it before looking at your comment and then back at the last line of @jremington's comment.

@Johnerrington.
Thank you for all the advice. This is probably going to turn into a novel so I apologize in advance. The TLDR is I am trying to drive a differential op amp circuit to step up my sin wave to +-10-13V, then drive a push pull mosfet circuit, that then drives a step up transformer (10:1 turns ratio, 40VA). All of this so I can play around with 40-70hz sine waves and do basic relay voltage/frequency testing without having to borrow a doble test set.

Background: I work in the power sector doing protective relay engineering. It has been over a decade since I have gotten to play around with my arduino, and even longer since I have done op amp circuits or filter circuits or any micro electronic design for that matter. I was cleaning out my house one day and saw my Arduino which gave me the idea to try to make a single or three phase inverter to do some voltage testing on a few relays. It would allow me to do some basic testing at home which would be convenient. Then I thought about the code for the arduino and I was fantasizing that I might even be able to build custom voltage waveforms to match some common fault conditions. Usually you have to use a large expensive test set to do this (which I understand, there is a reason it is large and expensive, but still, why not try right?). Also, I say voltage because I couldn't even begin to conceptualize how I would drive high current wave forms so I was just focusing on the relay's high impedance voltage inputs. I gave up on this idea after the first day because all of my searches were bringing up incomplete push pull circuits that magically transformed a nonmanipulated square wave into a working sine wave and I couldn't make any of them work, but it still bugged me at night and I kept thinking about it. I finally got to the point where I was running a 60hz square wave out of my pwm into an op amp circuit (because I had a few ua741's from college that I still had around). I used the op amp to get my +/- outputs by setting it up in a differential configuration. Then from there, I ran it through a push pull mosfet set up and then to a 10:1 transformer to get 70-110VAC on the high side. Of course, this looked like a very poor sin wave. So then I started looking into properly modeling a sin wave with a pwm pin, and after reading a bunch of posts on here, I got to the point where I am now. I can finally get a decent waveform on the lowside, but it is missing a lot. I am thankful that I posted though because every comment on here has been very helpful and given me really good direction on where to go next. I don't want to keep wasting your time, but I definitely appreciate all the input and any continued input from you guys.

This may be of interest

It's possible but not practical. The circuits would be fairly complicated for a sinewave.
It may be possible to just use a 50W audio amplifier with a BTL output

It is pretty normal to use a block wave to produce 230v AC from lead acid batteries or the like.
Often a 24 to 230V transformer with mid branch is used. The mid is connected to 12V. Both ends are connected (alternating out of phase) to ground via mosfets.
The transformer will remove some of the block shape (it is an inductor). A capacitor can remove more. Most 230V AC applications do not really care about the fact that it is not an exact sine wave...
https://images.app.goo.gl/2CQUcgMdFugR4Pf88

@Johnerrington: That is definitely of interest. Thank you! I will try to dig into it in the next few days.

@jim-p: I never thought of using an audio amplifier. I will have to look into that route as well.

@build_1971: That is similar to what I was looking at in the beginning and that makes a whole lot of sense. A part of me wants to branch down that road at some point now that my interest has been peaked. I am trying for a cleaner sin wave because it is for testing some settings in relays (I.E. A GE L90 or a SEL 311L etc...)

Why not drive a DAC from the Arduino to generate a sine wave directly? Saves having to filter things and works over a wide range of frequencies.

Or even use high speed PWM with analogWrite() with a simple RC filter on the output?

@MarkT: I was under the impression that you could only drive one DAC per board So I went with the high speed PWM option as I was hoping to drive multiple phases in the future. I had this working great for low frequencies but I had my RC filter designed poorly. That is what initiated my post. Then @johnerrington, @jremington, and @build_1971 helped me solve that very quickly and @johnerrington led me to realize that I also had my PWM pins set to too low of a frequency with respect to the onboard clock since my Atmega is an older board. Once this was solved, I was able to get a decent sin wave output at higher frequencies with a higher number of sampling points. Now I am just playing around and cleaning it up when I have time while using the website @johnerrington provided to help me clean it up.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.