OCR1A and duty cycle

how does OCR1A work. in my coding it did not execute any thing. is it my coding wrong? i wanna use A0 to control the duty cycle from 0% to 100% is it possible??

// Variables
float inputVoltage, duty;
const float outputVoltage = 10.0; // Sets output voltage to 10V

// Pin Configuration
const int pwmPin = 9;
const int voltagePin = A0;

void setup() {
  pinMode(pwmPin,OUTPUT); // Set PWM pin 9 as output
  TCCR1A = _BV(COM1A1) | _BV(COM1B1) | _BV(COM1B0); // Non-inverted mode
  // TCCR1A = _BV(COM1A1) | _BV(COM1B1) | _BV(COM1A0) | _BV(COM1B0); // Inverted Mode
  TCCR1B = _BV(WGM13) | _BV(CS11); // Selects prescaler N = 8
  ICR1 = 12.5; // Sets frequency to 83kHz
  OCR1A = 15624; // Sets PWM duty cycle 
}

void loop() {
  inputVoltage = (float)analogRead(voltagePin)/1023.0*5.0; // Reads input voltage
  duty = 1 - inputVoltage/outputVoltage; // Computes the theoretical duty cycle %
  duty = duty*2.55; // Scales the duty cycle percentage into 0 - 255
  OCR1A = int (duty); // Loads the desired duty cycle into duty cycle register
}

Uh....

You know you could just do...

// Variables
const float outputVoltage = 10.0; // ???

// Pin Configuration
const int pwmPin = 9;
const int voltagePin = A0;

void setup() {
  pinMode(pwmPin,OUTPUT); // Set PWM pin 9 as output
}

void loop() {
  analogWrite(pwmPin,255-(analogRead(voltagePin)>>3))
}

But that doesn't set the frequency, which presumably you need.

You're doing a number of things wrong:
Registers do not accept float values - you cannot set ICR1 to 12.5.

More importantly, you do not appear to have read section 16 of the datasheet which explains how the timer/counter actually works.

The timer counts between 0 and ICR1 in that mode, and the pin changes when the counter reaches OCR1A (and OCR1B for the other pin). What that means is that:
a) resolution is limited by ICR1
b) you need to set OCR1A to values between 0 and ICR1 to get PWM output (otherwise it's always on or always off)

ICR of 12 and prescaler of 8 does indeed get you 83.3 khz - but you only get to adjust it in 12 steps!

So back off on the prescaler to 1 (CS10 instead of CS11), and kick ICR1 up to 96 (8 times 12).

Then you could use the rest of your code unchanged (though there's certainly room for improvement) except for the calculation of duty, where you'd need to get it into a range from 0-96 (which is all the resolution you have - you can double that by switching to fast PWM mode and doubling ICR)

 TCCR1B = _BV(WGM13) | _BV(CS11); // Selects prescaler N = 8
  ICR1 = 12.5; // Sets frequency to 83kHz

ICR1 is an integer, so it can't be 12.5. That will be taken as 12.

1 / (12 * 8 * 62.5e-9) / 2 = 83333 Hz

However the duty cycle is now a number between 0 and 12. For example, if OCR1A is 6 you will have a 50% duty cycle. If it is 3 you will have a 25% duty cycle.

  duty = duty*2.55; // Scales the duty cycle percentage into 0 - 255

No, you need to scale it into 0 to 12. It is the number of timer counts that the output pulse is high.

Plus what DrAzzy typed while I was writing my response. :slight_smile:

how can i scale it to to 12?

i want to have a fixed output voltage of 10V and my input voltage is able to vary from 1V to 5V at my boost converter. So i need the microcontroller to control my mosfet driver to vary the duty cycle by itself. in order for me to get a continuous current wave form. do u have any ideas of doing it? or any coding i need to add to adjust this? thanks

pulse-width-modulation.jpg

I get the impression you just ignored my previous answer.

Thanks for telling me, i have change my mistake.
but for the OCR1A, i am still unsure about it. Do u mean that i have to change the OCR1A or the
duty = duty*2.55; // Scales the duty cycle percentage into 0 - 255 ??

Sorry i am new to this programming.

// Variables
const float outputVoltage = 10.0; // ???

// Pin Configuration
const int pwmPin = 9;
const int voltagePin = A0;

void setup() {
  pinMode(pwmPin,OUTPUT); // Set PWM pin 9 as output
}

void loop() {
  analogWrite(pwmPin,255-(analogRead(voltagePin)>>3))
}

I try it with my program by changing it and also the CS11 to CS10 but the current waveform is distorted.