I have a a function that is supposed to take in inputs and output a pwm signal that steps up its duty cycle over time. The function works almost and its the almost part that is driving me nuts. The first pulse should be high for a tenth of the period but its not. The pulse that does output first is what I would expect the second pulse to be. I am using a scope to verify the signal. When I have the while loop serial out the counter of the loop, 0-9 show as expected. What am I missing? For reference the inputs I have been using are pwm(0.1, 0.9, 10, 3000);
void pwm(float dutyStart, float dutyEnd, int cycles, int frequency)
{
int periodmicros = (int)(1000000/frequency); //frequency in Hz
float offset = (dutyEnd-dutyStart)/(cycles-1);
int i = 0;
while(i < cycles)
{
digitalWrite(10, HIGH);
delayMicroseconds(dutyStartperiodmicros); //Stay high for the duty cycle
digitalWrite(10, LOW);
delayMicroseconds(periodmicros-(dutyStartperiodmicros)); //Stay low for the remainder of the period
dutyStart += offset; //Increments the duty cycle by the average.
i++;
}
}
void pwm(float dutyStart, float dutyEnd, int cycles, int frequency)
{
int periodmicros = (int)(1000000/frequency); //frequency in Hz
float offset = (dutyEnd-dutyStart)/(cycles-1);
int i = 0;
while(i < cycles)
{
digitalWrite(10, HIGH);
delayMicroseconds(dutyStartperiodmicros); //Stay high for the duty cycle
digitalWrite(10, LOW);
delayMicroseconds(periodmicros-(dutyStartperiodmicros)); //Stay low for the remainder of the period
dutyStart += offset; //Increments the duty cycle by the average.
i++;
}
}
delayMicroseconds(dutyStart*periodmicros); //Stay high for the duty cycle
how long (micros) does this take to compute??
delayMicroseconds(periodmicros-(dutyStart*periodmicros)); //Stay low for the remainder of the period
again..same thing..
i doubt this is valid for any microsenconds() function..
this is like trying to time a bullet with a stopwatch..
@bwj, I disagree. delayMicroseconds() is okay for this. You just need to precompute integer timing values before you begin the while loop. But digitalWrite() takes some time. It would be good to use port manipulation for the output pin. Also, you seem to be overlooking the fact that your solution hard codes the number of NOP's.
The ultimate solution is using a timer with an output compare pin.
On mobile and can not seem to reply to specific posts, so general it is. The accuracy is not terribly important, but I would like to be as accurate as possible. Precalculating the values for the delay would be a great fix to try but as the delay being calculated is dependant on incrementing in the loop I am unsure how to do it unless I pull from an external array which may work but will eat memory. I looked at just doing this with timers but the accuracy of the frequencies seemed lacking, the frequency required will vary greatly and the pwm function will be called for up to outputs, theres a multiplexer in my future. I can look at the nop solution when I am near a scope. I hope that answers questions if not shoot back at me. Also I could not seem to find reponse time for digital write anyone know. Oh, also lastly the loop seems to workish. Its just outputting what would be expected to be pulse width two as one and the last pulse width is longer by the average.