Go Down

Topic: how to setup the pwm frequency of ATmega16U2  (Read 1 time) previous topic - next topic

laoadam


DaleScott

#1
Jan 02, 2019, 10:56 pm Last Edit: Jan 02, 2019, 11:15 pm by DaleScott
The reference library does not indicate any way to control the PWM frequency via Arduino code. It appears to be fixed at 490 Hz (980 Hz for pins 5 and 6 on the UNO). I only see a way to adjust the duty factor with the analogWrite(x,n) function. See https://www.arduino.cc/reference/en/language/functions/analog-io/analogwrite/ for details.

Could you accomplish your goal using the tone function? It allows you to change frequency?
(Duty factor fixed at 50%)
See : https://www.arduino.cc/reference/en/language/functions/advanced-io/tone/

DrAzzy

What core are you using for the 16u2? I didn't realize there was an Arduino core for the 16u2, despite that many arduino boards use it programmed to act as a USB<->Serial bridge.

But as with most Arduino boards, to change the PWM frequency, you have to take over one of the timers and manually set the prescaler (and maybe TOP value) - see the datasheet section on the timers, and know that timer0 is generally used for millis() (but check the docs for your core)
ATtiny core for 841+1634+828 and x313/x4/x5/x61/x7/x8 series Board Manager:
http://drazzy.com/package_drazzy.com_index.json
ATtiny breakouts (some assembled), mosfets and awesome prototyping board in my store http://tindie.com/stores/DrAzzy

DaleScott

Hmm.  Found this! Might be useful!

https://www.arduino.cc/en/Tutorial/SecretsOfArduinoPWM

laoadam

#4
Jan 04, 2019, 04:13 am Last Edit: Jan 04, 2019, 04:27 am by laoadam
I found this:

https://playground.arduino.cc/Code/PwmFrequency

can setup the PWM frequency by  a divisor, and the note that this function will have side effects on anything else that uses timers.

My question is can the board recover from this change if I used it for another program?
Thanks

I mean I want to load this sketch into my Arduino uno for test, and I will use my uno for another sketch after,  if it's ok?

MorganS

"The problem is in the code you didn't post."

laoadam

Thank you MorganS。

Is it possible to make the code available for Arduino UNO?

void setPwmFrequency(int pin, int divisor) {
  byte mode;
  if(pin == 5 || pin == 6 || pin == 9 || pin == 10) {
    switch(divisor) {
      case 1: mode = 0x01; break;
      case 8: mode = 0x02; break;
      case 64: mode = 0x03; break;
      case 256: mode = 0x04; break;
      case 1024: mode = 0x05; break;
      default: return;
    }
    if(pin == 5 || pin == 6) {
      TCCR0B = TCCR0B & 0b11111000 | mode;
    } else {
      TCCR1B = TCCR1B & 0b11111000 | mode;
    }
  } else if(pin == 3 || pin == 11) {
    switch(divisor) {
      case 1: mode = 0x01; break;
      case 8: mode = 0x02; break;
      case 32: mode = 0x03; break;
      case 64: mode = 0x04; break;
      case 128: mode = 0x05; break;
      case 256: mode = 0x06; break;
      case 1024: mode = 0x07; break;
      default: return;
    }
    TCCR2B = TCCR2B & 0b11111000 | mode;
  }
}

laoadam

#7
Jan 04, 2019, 10:05 pm Last Edit: Jan 04, 2019, 10:30 pm by laoadam
Hi,
any one can help me to make this code from: https://playground.arduino.cc/Code/PwmFrequency

works on arduino uno?

Code: [Select]


Here are some usage examples of the function:

// Set pin 9's PWM frequency to 3906 Hz (31250/8 = 3906)
// Note that the base frequency for pins 3, 9, 10, and 11 is 31250 Hz
setPwmFrequency(9, 8);

// Set pin 6's PWM frequency to 62500 Hz (62500/1 = 62500)
// Note that the base frequency for pins 5 and 6 is 62500 Hz
setPwmFrequency(6, 1);

/**
 * Divides a given PWM pin frequency by a divisor.
 *
 * The resulting frequency is equal to the base frequency divided by
 * the given divisor:
 *   - Base frequencies:
 *      o The base frequency for pins 3, 9, 10, and 11 is 31250 Hz.
 *      o The base frequency for pins 5 and 6 is 62500 Hz.
 *   - Divisors:
 *      o The divisors available on pins 5, 6, 9 and 10 are: 1, 8, 64,
 *        256, and 1024.
 *      o The divisors available on pins 3 and 11 are: 1, 8, 32, 64,
 *        128, 256, and 1024.
 *
 * PWM frequencies are tied together in pairs of pins. If one in a
 * pair is changed, the other is also changed to match:
 *   - Pins 5 and 6 are paired on timer0
 *   - Pins 9 and 10 are paired on timer1
 *   - Pins 3 and 11 are paired on timer2
 *
 * Note that this function will have side effects on anything else
 * that uses timers:
 *   - Changes on pins 3, 5, 6, or 11 may cause the delay() and
 *     millis() functions to stop working. Other timing-related
 *     functions may also be affected.
 *   - Changes on pins 9 or 10 will cause the Servo library to function
 *     incorrectly.
 *
 * Thanks to macegr of the Arduino forums for his documentation of the
 * PWM frequency divisors. His post can be viewed at:
 *   http://forum.arduino.cc/index.php?topic=16612#msg121031
 */
void setPwmFrequency(int pin, int divisor) {
  byte mode;
  if(pin == 5 || pin == 6 || pin == 9 || pin == 10) {
    switch(divisor) {
      case 1: mode = 0x01; break;
      case 8: mode = 0x02; break;
      case 64: mode = 0x03; break;
      case 256: mode = 0x04; break;
      case 1024: mode = 0x05; break;
      default: return;
    }
    if(pin == 5 || pin == 6) {
      TCCR0B = TCCR0B & 0b11111000 | mode;
    } else {
      TCCR1B = TCCR1B & 0b11111000 | mode;
    }
  } else if(pin == 3 || pin == 11) {
    switch(divisor) {
      case 1: mode = 0x01; break;
      case 8: mode = 0x02; break;
      case 32: mode = 0x03; break;
      case 64: mode = 0x04; break;
      case 128: mode = 0x05; break;
      case 256: mode = 0x06; break;
      case 1024: mode = 0x07; break;
      default: return;
    }
    TCCR2B = TCCR2B & 0b11111000 | mode;
  }
}


vaj4088

Anyone attempting to answer this is likely to need the function setPwmFrequency defined at

http://playground.arduino.cc/Code/PwmFrequency


laoadam

Thank you vaj4088.
Sorry that I missed the main code and done supplement.

laoadam

I followed the thread of PWM frequency library and tested the following code, I really can't feel the LED's  brightness change when I changed the frequency from 5 to 20000. I just wonder what I did wrong?
I download [Arduino PWM Frequency Library v_05], unzip and put into Libraries.

Code: [Select]


#include <PWM.h>

//use pin 11 on the Mega instead, otherwise there is a frequency cap at 31 Hz
int led = 7;                // the pin that the LED is attached to
int brightness = 0;         // how bright the LED is
int fadeAmount = 5;         // how many points to fade the LED by
int32_t frequency = 20000; //frequency (in Hz)

void setup()
{
  //initialize all timers except for 0, to save time keeping functions
  InitTimersSafe();

  //sets the frequency for the specified pin
  bool success = SetPinFrequencySafe(led, frequency);
 
  //if the pin frequency was set successfully, pin 13 turn on
  if(success) {
    pinMode(13, OUTPUT);
    digitalWrite(13, HIGH);   
  }
}

void loop()
{
  //use this functions instead of analogWrite on 'initialized' pins
  pwmWrite(led, brightness);

  brightness = brightness + fadeAmount;

  if (brightness == 0 || brightness == 255) {
    fadeAmount = -fadeAmount ;
  }     
 
  delay(30);     
}


pert

Brightness is not controlled by frequency. Brightness is controlled by duty cycle.

https://en.wikipedia.org/wiki/Pulse-width_modulation

laoadam

Thank you pert,
can you kindly add some code to make it be able to control the brightness of LED?

sterretje

Which board are you using?

Pin 7 on e.g. an Uno is not a PWM pin, so that might be one of your problems. It will (probably) work if the library supports software PWM; for you to figure that out as I'm not familiar with the library.
If you understand an example, use it.
If you don't understand an example, don't use it.

Electronics engineer by trade, software engineer by profession. Trying to get back into electronics after 15 years absence.

Coding Badly

#14
Jan 05, 2019, 07:51 am Last Edit: Jan 05, 2019, 07:52 am by Coding Badly

@laoadam, please stop cross-posting.  Multiple threads merged.

This appears to be the actual goal...
Thank you pert,
can you kindly add some code to make it be able to control the brightness of LED?

Go Up