change pwm frequency of arduino uno

i want to generate pwm frequency in arduino uno 31khz and the duty cycle based on the analog input signal and i used this code and simulate it on proteus but there in no result at all.

/*
 * This is an example code for a BOOST converter circuit made with arduino + feedback
 * The feedback is connected to A1 and we set the desired voltage with a
 * potnetiometer connected to A0.
 * 
 * Subscribe: http://www.youtube.com/c/electronoobs
 * webpage: http://www.electronoobs.com/eng_circuitos_tut10.php
 */

 
int potentiometer = A0; //The input from the potentiometer is A0
int feedback = A1;      //The feedback input is A1
int PWM = 3;            //Digital pin D3 por PWM signal
int pwm = 0;            //Initial value of PWM width

void setup() {
  pinMode(potentiometer, INPUT);
  pinMode(feedback, INPUT);
  pinMode(PWM, OUTPUT);  
  TCCR2B = TCCR2B & B11111000 | B00000001;    // pin 3 and 11 PWM frequency of 31372.55 Hz
}

void loop() {  
  float voltage = analogRead(potentiometer);    //We read the value of the potentiometer, which is the desired value
  float output  = analogRead(feedback);         //We read the feedback, which is the real value

  //If the desired value is HIGHER than the real value, we increase PWM width
  if (voltage > output)
   {
    pwm = pwm+1;
    pwm = constrain(pwm, 1, 254);
   }
   
  //If the desired value is LOWER than the real value, we decreaase PWM width
  if (voltage < output)
   {
    pwm = pwm-1;
    pwm = constrain(pwm, 1, 254);
   }

   analogWrite(PWM,pwm);  //Finally, we create the PWM signal
}

To get a specific frequency you have to use a PWM mode where you can set TOP.

16 MHz / 31 kHz = 516.129 counts

Timer2 is an 8-bit timer so you can't use a TOP higher than 255. To get down to 31 kHz on Timer2 you will need to prescale the clock. Using a pre-scale of 8 you will be using a 2 MHz clock.

2 MHz / 31 kHz = 64.516

2 MHz / 64 = 31250 Hz
2 MHz / 65 = 30769.23 Hz (slightly closer)

Set TOP to 64 to get 65 counts. You will be able to select among 65 levels of PWM (0 to 64).

Try this:

#define MAX_OC2A    63

const uint8_t pinOC2B = 3;

void setup() 
{
    //31kHz gives a period of ~32.258uS
    //@62.5nS/tick --> 492.49 ticks
    //@500nS/tick (next prescaler /8) -> 64.5ticks
    //use 64 ti give 31250Hz
    pinMode( pinOC2B, OUTPUT );
    TCCR2A = _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
    TCCR2B = _BV(WGM22) | _BV( CS21 );
    OCR2A = MAX_OC2A;
    OCR2B = 0;
    
}//setup

void loop() 
{
    static uint8_t
        pwmVal=0;
    static uint32_t
        timePWM;
    uint32_t
        timeNow = millis();

    if( timeNow - timePWM >= 20ul )
    {
        timePWM = timeNow;
        analogWriteT2( pwmVal++ );
        if( pwmVal == 255 )
            pwmVal = 0;
    }//if
    
}//loop

void analogWriteT2( uint8_t npwm )
{
    uint8_t
        newPWM = map( npwm, 0, 255, 0, MAX_OC2A );

    if( newPWM == 0 || newPWM == 63 )
    {
        digitalWrite( pinOC2B, (newPWM==0)?LOW:HIGH );
        TCCR2A &= ~_BV(COM2B1);
        
    }//if
    else
    {
        TCCR2A |= _BV(COM2B1);
        OCR2B = newPWM;
        
    }//else
    
}//analogWriteT2

If you find that being limited to ~64 steps of PWM with an 8-bit timer gives steps that are too coarse, Timer 1 is a 16-bit timer which would give much finer granularity.

there is no output

engma:
there is no output

My oscilloscope begs to differ. :slight_smile: