How to generate pwm with 35% duty cycle at 250 hz using arduino

Hello,

I want to create a square wave of 250Hz on 35% duty cycle.

i try to do my best of my knowledge in code

#define ledPin 13

void setup()
{
  pinMode(ledPin, OUTPUT);

  // initialize timer1 
  noInterrupts();           // disable all interrupts
  TCCR1A = 0;
  TCCR1B = 0;

  TCNT1 = 65536;            // preload timer 65536-16MHz/256/2Hz
  TCCR1B |= (1 << CS10);    // 256 prescaler 
  TIMSK1 |= (1 << TOIE1);   // enable timer overflow interrupt
  interrupts();             // enable all interrupts
}

ISR(TIMER1_OVF_vect)        // interrupt service routine that wraps a user defined function supplied by attachInterrupt
{
  TCNT1 = 65536;            // preload timer
  digitalWrite(ledPin, digitalRead(ledPin) ^ 1);
}

void loop()
{
  // your program here...
}

Any suggestion :open_mouth:

I want to create a square wave of 250Hz on 35% duty cycle.

You can't have a square wave that doesn't have a 50% duty cycle.

You could try using the servo library and modifying the constants in the servo.h file.

Boardburner2:
You could try using the servo library and modifying the constants in the servo.h file.

Hi Boardburner2,
using the libe will slow down the process,

this is what i have so far with help of #clawson in Avrfreaks

void setup() {

TCCR1A = (1 << COM1A1) | (1 << WGM11); // pin low at match, WGM=14
TCCR1B = (1 << WGM13) | (1 << WGM12);
OCR1A = 22400; // 35% of 64000
ICR1 = 63999; // 64000 is 250Hz on 16MHz clock
TCCR1B |= (1 << CS10); // start timer at full speed
}

void loop() {
}

AWOL: You can't have a square wave that doesn't have a 50% duty cycle.

Why not?

I would use the hardware PWM. You just have to set up the registers right. For exactly 250Hz you have to mess with TOP as well. If 245Hz is fine you can use timer2 (pin3 and 4) with a prescaler of 128.

AWOL: You can't have a square wave that doesn't have a 50% duty cycle.

i'm confused now, why we can't

septillion: Why not?

Because if it's not 50%, it's a rectangular wave.

AWOL: Because if it's not 50%, it's a rectangular wave.

You might be right!

but i think we can still read it as square wave

This page show how http://maxembedded.com/2012/01/avr-timers-pwm-mode-part-ii/

AWOL:
Because if it’s not 50%, it’s a rectangular wave.

its ok if not rectangular wave, the most importing is Send the signal as Duty cycle.

this what i have so far, I still need help please

/*
So to get  250Hz we will be wanting a timer to keep counting from 0 to 63999 
(the 0 counts as one tick so you only go as far as 64000-1).
 
35% of 64000 is 22,400. So we will want the output state of the  
PWM to switch state when the timer has counted to 22,400.
 
To do this we are going to need a PWM mode where you can 
adjust both the TOP (frequency) and OCR (duty) values.
 
Looking at the 2560 datasheet and the "Waveform Generation Mode 
Bit Description" table it looks like mode 14 (WGM13, WGM12, WGM111 all 1, WGM10=0) 
fits the bill. In that mode you set TOP using ICR1
*/

int btn1 = 4;
void setup() {
////pinMode(btn1,OUTPUT); 
//
//DDRB |= (1 << DDB5) ;
//
//OCR1A = 22400; // 35% of 64000
//
//TCCR1A = (1 << COM1A1) | (1 << WGM11) | (1 << WGM10); // pin low at match, WGM=15
//TCCR1B = (1 << WGM13) | (1 << WGM12);
//
////ICR1 = 63999; // 64000 is 250Hz on 16MHz clock
//TCCR1B |= (1 << CS10); // start timer at full speed

   DDRB |= (1 << DDB5);
   // PB1 as output
    OCR2 = 128;

   // set PWM for 50% duty cycle at 10bit
   TCCR2A |= (1 << COM2A1);
   // set non-inverting mode
   TCCR2A |= (1 << WGM21) | (1 << WGM20);
   // set 10bit phase corrected PWM Mode
   TCCR2B |= (1 << CS20);
   // set prescaler to 8 and starts PWM
}

void loop() {
 //digitalWrite(btn1,HIGH); 

}

If you want something quick and dirty, which may not handle the micros() rollover perfectly (every c. 70 Minutes ) you can try this. Don’t put too much else in the loop().

void setup() {
 pinMode( 13, OUTPUT) ;
}

void loop() {
 // 250 Hz @ 35% duty cycle  =  cycle time of 4.0 mS =  1.4 mS on and 2.6 mS off.
 digitalWrite( 13, micros()%4000 < 1400 ) ;
}

Ignoring the whole "when is a square not a square" red-herring, the two ways to do this are to write some code to look at micros(), or to manipulate the timer as ON16 suggests.

Actually … I always find the same thing when working with steppers: having to leave 4ms between steps. How about that? I use the "blink without delay" pattern and work with micros() to time appropriate intervals.

GON16: Hi Boardburner2, using the libe will slow down the process,

Why. What are you trying to achieve ?

Boardburner2:
What are you trying to achieve ?

PaulMurrayCbr:
Actually … I always find the same thing when working with steppers

It have to be very effective with no delay(using Timers). In use for real world application.

6v6gt:
If you want something quick and dirty

Thank You All for help and reply

BUT after a whole day of research and testing i was able to get the code up and running.
but not as i wish. the code that i have is limited to 10 bit output and maximum of 75% duty cycle.
what I’m trying to do is send 16 bit output PWM at changeable duty cycle.
the reason for 16 bit is to have a higher resolution signal.
I want to have full control on the duty cycle to send it on a range of 1% to 100%
the duty cycle will be my data that i’m sending to the other device
the other device will read the duty cycle as data coming and react differently depending on the duty cycle coming in.

any suggestion that can help me please
this what i have so far

void setup() {
  // put your setup code here, to run once:

}
int main(void)
{
   DDRB |= (1 << DDB5);
   // PB1 as output
   OCR1A = 0x02FF;
   // set PWM for 50% duty cycle at 10bit
   TCCR1A |= (1 << COM1A1);
   // set non-inverting mode
   TCCR1A |= (1 << WGM11) | (1 << WGM10);
   // set 10bit phase corrected PWM Mode
   TCCR1B |= (1 << CS11);
   // set prescaler to 8 and starts PWM
   while (1)
   {
   }
}
void loop() {
  // put your main code here, to run repeatedly:

}

You can’t use the timer hardware to get both full 16-bit PWM and a 250 Hz cycle time. As you saw, to get exactly 250 Hz you need to set TOP to 63999. TOP also sets the upper limit for your PWM so you are limited to 15.96578 bit PWM. Is that not close enough?

You can get 16-bit PWM at 244.140625 Hz or you can use a non-standard crystal (16.384 MHz) to push that up to 250 Hz but you can’t do 16-bit 250 Hz PWM with the standard 16 MHz clock.

hi johnwasser Thank you for the information.

Its Working !!

int main()
{
  DDRL |= 0x08;   //Ser OCR5A pin to output
  ICR5 = 63999;   //Set TOP value 
  OCR5A = 8000;    //Set Duty cycle???
  TCCR5A |= 0x82;   //1000-0010 Set COM bits and the first two waveform generator bits
  TCCR5B |= 0x19;   //0001-1010 Set second two waveform generator bits and prescalar 

  while(1)
  {
    //DDRD |= 0x01;
  }

}

P.S i found this link here and i think they had the same issue like me here

LINK http://www.avrfreaks.net/forum/atmega8-16-bit-fast-pwm-ocr1a-solved

I think that you need to clear the presets from the timer registers. Begin your code with

TCCR5A = 0;
TCCR5B =0;

I think that you are carrying a default bit into WGM50 and actually setting Fast PWM to OCR5A.