microseconds() function probelms

I am designing a hybrid charge controller (solar cum wind).
I am facing some probelms in this:
Firstly i had to design a buck converter which will step down to a paricular voltage as per duty cycle set.
I am using 20K hz frequency.
The first this i observed was for 20K time period =50us but on CRO after programing arduino for 50us (with duty cycle=50%) using microseconds() function it showed around 18.83khz. So the at 36us i got 20khz .Hence in my programing i have written 36us as time period (which in actual corresponds to 20k and not 27.77k).
So coming to programing:
here is the program to get stepped down voltage by varying duty cycle:

int freq=10; //pulses of 20Khz at pin 9 named freq

//int i=minvalue;
  int i=0;   //for 24V its giving 13.18V across battery

void setup()
{
  // put your setup code here, to run once:
  pinMode(freq,OUTPUT);     //make freq a output pin

}

void loop()
{

digitalWrite(freq,HIGH);
delayMicroseconds(i);    
digitalWrite(freq,LOW);
delayMicroseconds((36-i));  //36us=time period
}

Now what is expected is when i make i=0 ==>pin 10 will always remain low hence o/p voltage=0V and solar panel voltage should be =open circuit voltage.But, exactly opposite is happening.
And when i make i=1 that time it’s behaving as required.
Same is the case when i=36==>pin 10 will always remain high hence solar panel voltage should dip/become as low as how much load is demanding but, no this isn’t happening solar panel voltage sits at it’s max voltage.
Now when i=35 it’s behaving as required.
Why these contradictory results only on boundary conditions?

Have you read the documentation on 'delayMicroseconds?

documentation:
This function works very accurately in the range 3 microseconds and up. We cannot assure that delayMicroseconds will perform precisely for smaller delay-times.

And 'delayMicroseconds(0)' will still take some time, because the instruction itself takes time to execute.
If you want accurate PWM at this frequency, you really need to directly use a timer, or perhaps the "PWM Frequency" library.

Also, of course, as soon as you add more code to 'loop()', your timing goes right out the window.

int freq=10; //pulses of 20Khz at pin 9 named freq

I see. Where is 20 or 9 in this assignment?

Another issue is that between each iteration of loop(), the arduino does other stuff. For instance, it checks the USB to see if there is another sketch coming down the pipe. You can make the loop tighter by putting your code in a

while(1) {
  do stuff;
}

But I think this means you have to reset the board to upload a new sketch onto it. Which isn't a massive hassle.

At the end of the day, if you want to do stuff at 20kHz, you really might be better off with some sort of hardware solution. Or you could explore the wonderful world of Programmable Logic Arrays. Those bad boys switch at nanosecond rates.

OldSteve:
If you want accurate PWM at this frequency, you really need the "PWM Frequency" library.

I use arduino due can i use pwm library for this one?

dishak:
I use arduino due can i use pwm library for this one?

No, it doesn't work with Due or Leonardo, according to the documentation and relevant forum thread.
If you search, ther might be a similar library for Due.
Otherwise, you'll need to do it yourself, directly manipulating the timers.

thanks,
I am using this library:
http://playground.arduino.cc/Code/Timer1

dishak:
thanks,
I am using this library:
http://playground.arduino.cc/Code/Timer1

Will it work with the Due?

From the link that you posted:-

This library is a collection of routines for configuring the 16 bit hardware timer called Timer1 on the ATmega168/328.

I tested the code that they have provided (the first one) it worked blinking the led

dishak:
I tested the code that they have provided (the first one) it worked blinking the led

Good. You're in business then, I guess, if it blinks at 20kHz.
Have you tried varying the duty-cycle through the full range that you need, while monitoring on the oscilloscope?

Edit: One or two seconds at each duty cycle might be needed, to be able to see it properly.

OldSteve:
Good. You're in business then, I guess, if it blinks at 20kHz.
Have you tried varying the duty-cycle through the full range that you need, while monitoring on the oscilloscope?

Edit: One or two seconds at each duty cycle might be needed, to be able to see it properly.

but i have some doubts here is the code below:
#include "TimerOne.h"

void setup()
{
pinMode(10, OUTPUT);
Timer1.initialize(500000); // initialize timer1, and set a 1/2 second period
Timer1.pwm(9, 512); // setup pwm on pin 9, 50% duty cycle
Timer1.attachInterrupt(callback); // attaches callback() as a timer overflow interrupt
}

void callback()
{
digitalWrite(10, digitalRead(10) ^ 1);
}

void loop()
{
// your program here...
}
In this they called timer1.pwm in void setup() whereas voidsetup() executes only once. And does timer resets only when isr is executed or have i too clear the timer flag?

You already know that you should always use code tags when posting code.
Please edit your post and do that.

I've never used that library. Read the documentation thoroughly. (Better you than me. :slight_smile: )
I would think that it happens automatically. Have you connected the 'scope to verify that you're getting what you want?