New User Get $30 User Coupons https://jlcpcb.com/CYT
Other Users Get SMT Coupons via Contacting JLCPCB Facebook
The Arduino Uno, Nano and Pro Mini all have PWM frequencies of 490Hz (on outputs 3, 11, 8 and 9) and 976Hz (on outputs 5 and 6). In this video I tweak the frequency from 490Hz to exactly 1kHz.
Subscribed to my 2nd channel? Watch all my 3 minute videos on Julian's Shorts: https://www.youtube.com/channel/UCeewzdnwcY5Q6gcbnZKIY8g
Interested in my new garden workshop? Follow the entire build on Julian's Shednanigans:
https://www.youtube.com/channel/UCXfDjPehpC7B7lW2JFxeS4w
Join me on Odysee/LBRY: https://lbry.tv/$/invite/ @julian256:d
Octopus Energy referral link: share.octopus.energy/aqua-birch-918
(We each get £50)
#EasyEVSE
#ElectronicsCreators

Good morning, all this arduino can produce a pulse width, modulated square wave output, uh with variable pulse width, and i can use this potentiometer to vary that pulse width, but it doesn't produce a one, kilohertz uh square wave output and that's what i want one kilohertz. So today is all about me trying to tweak the pwm output from this arduino nano to make it one kilohertz. So let's put some power to the arduino uh lobber sketch into it, and check with the scope uh what's coming out of one of the pwm pins. So this is the code i'm going to put in the arduino uh, it's just a integer pot to do an analog read of a7.

That's where the pots connected uh divide, that by four, because an analog read is a 10 bit number that goes from 0 to 102 3.. When you write to a pwm, pin it's an 8 bit number 0 to 2 5 5. So i'm going to write it to pin 3 the value that we got into pot, let's compile and upload, and see what we get right. Let's switch the scope on got a spike or a pin.

It's a sort of dupont pin in there we'll put that in uh pin three now i need ground which i can get. If i stick it between those pins, it won't be able to swivel too much and short off out on the adjacent vcc right. Let's do an auto on there and see what we've got, and the problem here is that the uh frequency of the pwm - oh, let's make sure it's just responding to the pot which it is. It goes fully to 100 percent, fully to zero percent and obviously 50.

In the middle of the pots range of travel but yeah, the problem is 490 hertz, and now i want one kilohertz now. I believe that the frequency is different on other pins. Let's check that out. Yes, here on a google search for arduino pwm frequency, 490 hertz.

As we measured now on the uno, nano and the mini or pro mini uh, there's also a 980 hertz signal on pins five and six. So, let's quickly check that one out so here in the sketch i'm going to change this 3 in the analog write statement to a 5 and then we'll take a look at the output on pin 5 and check the frequency that sketch is uploaded. So i need to move this from pin three to pin five and there it is, and it's not actually 980 it's 977.. In fact, i've got a feeling that in the documentation it's described as 976 hertz, so it's not far off one kilohertz.

Now, for my evse, my electric vehicle uh charger, i actually need one kilohertz, but there is a tolerance on it. It's from 980 to 1020, 1020, hertz and 977 as measured here or 976. As i seem to remember it, being more precisely is just slightly under the uh lower level of the tolerance of an evse, a car charger which requires that it's no less than 980, so it's four hertz below. So what we really want to do is try and tweak the frequency to get it actually up to one kilohertz exactly one.

So kilohertz gone back to analog right on, pin three back to 490 hertz and what i'm going to do is i'm going to try and double that by changing the prescaler setting, and that would take us from 490 to 980. I think which is right at the bottom edge of the tolerance for a car charger. So, let's see if we can achieve that, so we need to go to the atmega328p there. It is 328p datasheet and scrolling down on here.
There's all sorts of information on how the uh hardware works for timer two now timer two is what generates pwm for output three and also output eleven. So let's take a look at what we need to change on timer 2 to change this prescaler. So that's what i'm looking for, i'm looking for the uh register that contains the prescaler information you do have to scroll down quite a long way. In fact, i'm going to click down here because we need registers right here.

We are, i think it's here now. These are the these are the settings for which output is producing a pwm, these com2a1, com2a, naught and so on, and so forth a little bit further down and we get yes here. It is in tccr2b. There are these cs2 bit 2 cs2 bit 1 and cs2 bit 0 and they are for the prescaler.

So here they are so cs2 bits two one and zero. Now i think the default is uh one: zero zero on those three bits which would be a decimal. Four that doesn't divide by 64.. What we want is to divide by 32 because we want to go twice as fast, so we want to change it from four to three.

So, let's see what happens if i just shove three into this register tccr2b now. What i really should do here is uh force the two lower bits high to put one one in there so or with three and force this bit low so and it with er. All ones a naught there and a couple of ones there, whatever that is so that we don't affect these other bits. They probably the other way we could do it is.

We could read out what's in that register, currently uh, just to make sure that we're not changing anything that we shouldn't be changing, but i think i'll do the ending and the auring. It is a bit messy, but uh it's the best way to not affect the rest of the bits in this register. This is what i want to do. I want to take tccr2b and make it equal, well, read, tccr2b and then change it.

So it's a read, modify, write to or which is a vertical bar, and i suppose i could do this in binary. Uh, oh and then set the bottom two bits so one one there uh do. I have to have b. I think it's um zero b and then that and then i want to and it with uh 0 b for binary, so it'll be 1, 1, 1, 1, 1 zero to pull bit two down and one one to not change bits uh, one and zero.

I think that's right, so, let's put that into the arduino and see what we get well, it's kind of sort of done something, but it's changed it to 30 hertz uh from 490 hertz. So it slowed it right down. I actually wanted to speed it up. So i've got something a little bit wrong.

Let's have a think about it. Yes, i think this acts kind of sequentially. So probably what i want to do is i don't want to. I want.

I want to zero out the bottom three bits. So if i ended with all zeros and then just push those two up so yeah, i think what i want to do is change these to all zeros and i'll. Do the and before the or so let's take that cut it out and stick it before the or uh? No, i didn't want to return there. I wanted to space i'll fix that and we'll see what it does.
Yes, that's done it, so that's changed the prescaler um to divide by 32 instead of divided by 64.. Now, that's actually given us 981 hertz, which is within the range of the evse square wave spec of 980 to 1020. But since we're here and we're messing around with registers, we might as well do a further tweak to try and get that exactly to one kilohertz. Now, as i understand it, um the arduino is set up initially on timer two for pwm phase, correct, with a top value of ff and a bottom value of zero.

Now i want to slightly tweak this top value. What happens is that the arduino counts up from zero to ff when it gets to ff. It starts counting back down again but flips the pwm output. So then, it counts all the way back down to zero flips the pwm output again and starts counting back up to ff.

Now. If i got it to count up to slightly less than ff it would do it a bit quicker, and you can do that because this mode here, which is mode 1, counts up to fff this mode, which is mode 5 or 101, counts up to whatever ocr A is now if we change ocr a we can get it to count up to a value, that's different to f, f, let's give that a try, and that means asserting or setting or pushing to a 1 the value of this bit. Wgm 2 waveform generator mode. Two, so let's go to the register right yeah! So it's this bit! It's wgm two bit two! I think that is so it's in bit, 3 of tccr 2b.

So it's once again tccr 2b. So we just want to push up bit 3.. That's all! We want to do so. I can add that to my code and that will change the mode so that no longer counts up to ff, but it counts up to whatever's in ocr to a let's try that so that is um.

Well, we can bring down bit three here with a zero and then push it back up here bit three with a one so and it to lower it and then or it push it back up again. So, let's upload that and see what the arduino does and it does precisely nothing now, that's because um ocr 2, a probably doesn't have a valid number in it. So, let's set it to well, let's set it to f e, slightly less than um what it was counting to before ff and just see whether that slightly tweaks, the frequency. So i've put this statement in here.

Ocr2A is hex decimal, f e. Let's upload that and just see whether that makes any difference: firstly, whether of course the pwm restarts but yeah, whether that tweaks, the frequency slightly. And yes, it does that's interesting. So that's now 985 hertz and that's because, if we're counting from zero zero, it counts up.

Zero, zero zero one zero, two all the way up to ff. Normally, when you have the uh pwm mode as it was now, it's only counting up to fe, then it counts all the way back down to zero and then up to fe again and every top and bottom, the pwm changes states. That's actually what we're seeing we're seeing the change of state. We just want to make it a bit quicker.
So let's bring that fe down to. I don't know f0. That might be too much actually, but let's give that a try see what happens. Okay, so i've just recompiled it with f0 as the top count and we're a bit high now we're 1.04 kilohertz.

So all i need to do now is just sort of empirically modify that value until i get exactly one kilohertz so i'll just play with that. For a bit and try and tweak it so that it's exactly one curves, oh there we are so i was kind of working iteratively. So i went for f, eight and yes, give me exactly one kilohertz and the pot should give me full uh, pwm, pulse width control over that one kilohertz square wave, so even with a short duration mark and the long duration space, it's still one kilohertz and similarly Up at the other end of the scale so yeah, with a couple of statements, we've managed to tweak the 490 hertz output from pin 3 pwm on pin 3 up to exactly one kilohertz, which is exactly where i want it, and the code for that is simply In the setup making some tweaks to tcc r2b, so the lower three bits of this are the prescaler. So we've gone from a 60 uh, divided by 64 pre-scale to a divided by 32 prescale that took us up to about 980 hertz and then by slightly oh and then by changing this bit bit.

Three we've gone to the other mode where, instead of counting up to ff, it counts up to whatever is in ocr2a and by slightly reducing that, from ff to f8. We're running the pwm hardware slightly faster and achieved the one kilohertz pwm output, ah yeah. So, that's it really! That's all i planned to do today. I just wanted to be able to create a one kilohertz pulse width, modulation, output.

Now, actually there's something quite interesting here, because the values that you send to the pwm hardware can't be well. They can be zero to f, f anymore. They have to be zero to f eight. This pot is still sending values zero to f, uh f, so the very last bit of travel of the pot doesn't do anything, but it doesn't matter too much.

I mean i can make adjustments for that in the software of whatever code. I end up having to vary the pulse width but yeah as long as you send values to the positive hardware, between zero and f, eight now or possibly, f. Seven. No, i think f8 would work if you wanted the full 100 permanently on uh.

Then yes, you'll get the full range of we've slightly reduced the range of pwm granularity. I suppose you'd call it from a full 256 different values to 248 or something like that. But essentially that's it. One kilohertz coming out password modulatable on pin three cheerio.


By Julian

Youtuber, shed dweller, solar charge controller aficionado

5 thoughts on “Arduino pwm frequency tweaked to 1khz”
  1. Avataaar/Circle Created with python_avatars PicoNano says:

    I like that little scope.

  2. Avataaar/Circle Created with python_avatars PicoNano says:

    I'm surprised someone hasn't created a library, to output any valid frequency the hardware PWM can generate!

  3. Avataaar/Circle Created with python_avatars sjm4306 says:

    It's always boggled my mind a bit why the default (in fact only) pwm frequency of the analogWrite function is so low frequency (~300Hz). The 328p can easily go up to ~62kHz (at the loss of some resolution), and easily past 1kHz while having plenty of resolution.

  4. Avataaar/Circle Created with python_avatars Marcus Jenkins says:

    This would be for your DIY EVSE, right?

  5. Avataaar/Circle Created with python_avatars Paul H says:

    Nice one. I've been missing these kind of videos!
    I'm following along with a Pro-Mini I had to hand. OCR2A = 0xF9 gets closer to 1kHz on my Rigol scope (exact, in fact).

    Grrr. You didn't set the pin input / output in setup()!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.