Arduino Forum

Using Arduino => General Electronics => Topic started by: laoadam on Jan 02, 2019, 09:22 pm

Title: how to setup the pwm frequency of ATmega16U2
Post by: laoadam on Jan 02, 2019, 09:22 pm
any one have a short Sketch to do it?
Title: Re: how to setup the pwm frequency of ATmega16U2
Post by: DaleScott on Jan 02, 2019, 10:56 pm
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/
Title: Re: how to setup the pwm frequency of ATmega16U2
Post by: DrAzzy on Jan 02, 2019, 11:56 pm
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)
Title: Re: how to setup the pwm frequency of ATmega16U2
Post by: DaleScott on Jan 03, 2019, 02:43 am
Hmm.  Found this! Might be useful!

https://www.arduino.cc/en/Tutorial/SecretsOfArduinoPWM
Title: about the pwm frequency
Post by: laoadam on Jan 04, 2019, 04:13 am
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?
Title: Re: about the pwm frequency
Post by: MorganS on Jan 04, 2019, 05:42 am
Yes.
Title: Re: about the pwm frequency
Post by: laoadam on Jan 04, 2019, 06:54 pm
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;
  }
}
Title: how to make this code works on Arduino UNO
Post by: laoadam on Jan 04, 2019, 10:05 pm
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;
  }
}

Title: Re: how to make this code works on Arduino UNO
Post by: vaj4088 on Jan 04, 2019, 10:12 pm
Anyone attempting to answer this is likely to need the function setPwmFrequency defined at

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

Title: Re: how to make this code works on Arduino UNO
Post by: laoadam on Jan 04, 2019, 10:32 pm
Thank you vaj4088.
Sorry that I missed the main code and done supplement.
Title: PWM.h can not fade led
Post by: laoadam on Jan 05, 2019, 12:41 am
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);     
}

Title: Re: PWM.h can not fade led
Post by: pert on Jan 05, 2019, 01:03 am
Brightness is not controlled by frequency. Brightness is controlled by duty cycle.

https://en.wikipedia.org/wiki/Pulse-width_modulation (https://en.wikipedia.org/wiki/Pulse-width_modulation)
Title: Re: PWM.h can not fade led
Post by: laoadam on Jan 05, 2019, 01:39 am
Thank you pert,
can you kindly add some code to make it be able to control the brightness of LED?
Title: Re: PWM.h can not fade led
Post by: sterretje on Jan 05, 2019, 06:59 am
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.
Title: Re: how to setup the pwm frequency of ATmega16U2
Post by: Coding Badly on Jan 05, 2019, 07:51 am

@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?
Title: Re: how to setup the pwm frequency of ATmega16U2
Post by: DrAzzy on Jan 07, 2019, 12:40 am
Which board are you using?
This is a critical detail which you seem allergic to posting, because since PWM frequency is not exposed to the user via the Arduino abstractions, you need to use a library or adjust the registers directly. And not all libraries for this support all boards, nor is the code the same for all boards.

You originally asked about the 16u2, which is not used as the main microcontroller in any official boards and which I was unaware of any Arduino support for programming it via the IDE - the only boards that use it use it as a usb-serial adapter for another microcontroller. Which led to my earlier questions (which you never answered).

Of course, if you just want to change the brightness of an LED connected to a PWM pin, you don't need to change the frequency, just the duty cycle - for that you can just use analogWrite() - though it's unclear whether there's some other reason you also need to change the frequency.
Title: Re: how to setup the pwm frequency of ATmega16U2
Post by: pert on Jan 07, 2019, 01:22 am
I was unaware of any Arduino support for programming it via the IDE
I only know of one 3rd party hardware package for it:
https://github.com/NicoHood/HoodLoader2 (https://github.com/NicoHood/HoodLoader2)
But I agree that laoadam needs to take a minute to provide the information needed to help them. If they had used their time to do that instead of cross posting, likely this would have been resolved days ago
Title: Re: how to setup the pwm frequency of ATmega16U2
Post by: vaj4088 on Jan 07, 2019, 02:35 am
If the pulse duration is held constant somehow, then changing the frequency would change the duty cycle.  PWM would then be the wrong name for what is happening.
Title: about use of PWM.h
Post by: laoadam on Jan 07, 2019, 03:34 pm
I am using Arduino UNO, I need to setup PWM frequency as 15K.

My question is if I use such as "analogWrite(ledPin, val / 4)" to control the motor speed, will the PWM frequenct keep same as set or change back the original。
Title: Re: about use of PWM.h
Post by: pert on Jan 07, 2019, 03:42 pm
If I understand from the previous thread, PWM.h is part of some library. Is that correct? If so, post a link to where you downloaded it from. Please use the chain links icon on the toolbar to make the link clickable.

Previous thread:
http://forum.arduino.cc/index.php?topic=588402 (http://forum.arduino.cc/index.php?topic=588402)
Title: Re: about use of PWM.h
Post by: DrAzzy on Jan 07, 2019, 06:52 pm
If all pwm.h changes is the prescaler, then analog write wont change it back - but if it is getting that frequency by also changing TOP, you need your own version of analog write to account for that.
Title: how to change the frequency of a pro micro's PWM
Post by: laoadam on Jan 09, 2019, 11:06 pm
I used a pro micro and a TB6612FNG dual motor driver to drive a small car, now I want to use another large motor driver, and which asked a higher PWM frequency of ~15KHz, how can I modify the sketch to fit the application?

The project come from this link originally: https://www.instructables.com/id/Arduino-RC-Gamepad/
and the code:
Code: [Select]

#include <VirtualWire.h>

/* ARDUINO RC GAMEPAD by TeamJaeger in Technology from https://www.instructables.com/id/Arduino-RC-Gamepad/
 *  saved to: E:\design_info\DIY\ARDUINO\01_ARDUINO RC GAMEPAD
 *  this sketch was designed to load to a PRO MICRO, will be modify to suit sth new
 */
 
//motor A connected between A01 and A02
//motor B connected between B01 and B02

int STBY = 10; //standby


//Motor A
int PWMA = 3; //Speed control
int AIN1 = 9; //Direction
int AIN2 = 8; //Direction

//Motor B
int PWMB = 5; //Speed control
int BIN1 = 6; //Direction
int BIN2 = 16; //Direction

const boolean FORWARD = HIGH;
const boolean REVERSE = LOW;
float speed_Max = 255; //pwm usually goes from 0-255
float speed_Min = 0;
float analogInput_Max = 1023;
float analogInput_Min = 0;
float analogInput_Middle_X = 515;//ideally it would be analogInput_Max / 2
float analogInput_Middle_Y = 495;//ideally it would be analogInput_Max / 2
float deadBand = 0;
float middleMax = (analogInput_Max / 2) + deadBand;
float middleMin = (analogInput_Max / 2) - deadBand;
boolean pastDirection = FORWARD;

void setup(){

Serial.begin( 9600 );

pinMode(STBY, OUTPUT);

pinMode(PWMA, OUTPUT);
pinMode(AIN1, OUTPUT);
pinMode(AIN2, OUTPUT);

pinMode(PWMB, OUTPUT);
pinMode(BIN1, OUTPUT);
pinMode(BIN2, OUTPUT);

//receiver setup
vw_set_rx_pin(2);          //Sets pin 12 as the RX Pin
vw_set_ptt_inverted(true); // Required for DR3100
vw_setup(2000);            // Bits per sec
vw_rx_start();             // Start the receiver PLL running
}

void loop(){

uint8_t buf[VW_MAX_MESSAGE_LEN]; // This declares a variable array. instead of 7 variables buf1, buf2 etc...
uint8_t buflen = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf, &buflen)) // Non-blocking
{
int i;
    int column = 0;
    String message;
    int commands[30];
   
        // Message with a good checksum received, dump it.
        for (i = 0; i < buflen; i++)
        {     
        //DEBUG:
        //Serial.print(char(buf[i]));
       
        if(char(buf[i]) == '|'){
        commands[column] = message.toInt();
        message = "";
        column++;
        }else{
        message += char(buf[i]);
        }
        }
        //one more time to capture the last value since the message does not end with |
        commands[column] = message.toInt();
       
        // DEBUG
// Serial.print("X: ");
// Serial.print(commands[0]);
// Serial.print(" Y: ");
// Serial.println(commands[1]);

motorControl(commands[0], commands[1]);

}

}

void move(int motor, int speed, boolean direction){
digitalWrite(STBY, HIGH); //disable standby

if(motor == 1){
digitalWrite(AIN1, direction);
digitalWrite(AIN2, !direction);
analogWrite(PWMA, speed);
}else{
digitalWrite(BIN1, !direction);
digitalWrite(BIN2, direction);
analogWrite(PWMB, speed);
}
}

void motorControl(float x, float y) {
boolean currentDirection = y >= analogInput_Middle_Y;

//map(value, fromLow, fromHigh, toLow, toHigh);
if(currentDirection == REVERSE){
y = map(y, analogInput_Middle_Y, analogInput_Min, speed_Min, speed_Max) ; 
}else{
y = map(y, analogInput_Middle_Y, analogInput_Max, speed_Min, speed_Max);
}
 
int subtractFromLeft = map(x, analogInput_Middle_X, analogInput_Min, speed_Min, y);
int subtractFromRight = map(x, analogInput_Middle_X, analogInput_Max, speed_Min, y);

if(subtractFromRight < 0){
subtractFromRight = 0;
}

if(subtractFromLeft < 0){
subtractFromLeft = 0;
}

int Throttle_RIGHT = y - subtractFromRight;
int Throttle_LEFT = y - subtractFromLeft;

boolean currentDirection_LEFT = currentDirection;
boolean currentDirection_RIGHT = currentDirection;


if(Throttle_LEFT < 1 && Throttle_RIGHT > 1){
currentDirection_LEFT = !currentDirection;
Throttle_LEFT = Throttle_RIGHT;
}

if(Throttle_RIGHT < 1 && Throttle_LEFT > 1){
currentDirection_RIGHT = !currentDirection;
Throttle_RIGHT = Throttle_LEFT;
}

move(1, Throttle_LEFT, currentDirection_LEFT);
move(2, Throttle_RIGHT, currentDirection_RIGHT);

// Serial.print("Throttle_LEFT: ");
// Serial.print(Throttle_LEFT);
// Serial.print(" Throttle_RIGHT: ");
// Serial.print(Throttle_RIGHT);
// Serial.println("");
//
// if(Throttle_LEFT >= -400 && Throttle_LEFT <= 400){
// motors.setM1Speed( Throttle_LEFT );
// }
//
// if(Throttle_RIGHT >= -400 && Throttle_RIGHT <= 400){
// motors.setM2Speed( Throttle_RIGHT );
// }
// delay(2);
 
}


Title: Re: how to change the frequency of a pro micro's PWM
Post by: pert on Jan 10, 2019, 08:52 am
Other than switching from ATmega16U2 to ATmega32U4, it seems like the same topic as your previous thread:
http://forum.arduino.cc/index.php?topic=588402 (http://forum.arduino.cc/index.php?topic=588402)
and
http://forum.arduino.cc/index.php?topic=589308 (http://forum.arduino.cc/index.php?topic=589308)
You had multiple people trying to help you in both those threads but instead of providing the information they are requesting, you either crosspost or just abandon the thread. Please just stick with a single thread, monitor that thread closely, and respond quickly to any information requests. If you do that, you are likely to get an answer to your question very quickly. Otherwise, you're just wasting everyone's time.
Title: Re: how to setup the pwm frequency of ATmega16U2
Post by: AWOL on Jan 10, 2019, 10:25 am
More threads merged.