The code is what selfonlypath posted a while ago. Note that this does NOT generate "very fast PWM signals"; it just uses the same PWM peripheral to generate a very fast waveform (2 bits of PWM. OFF and ON) To retain the 256-bit "analogWrite" capability, the overall frequency will need to be much lower. Still, you can probably get something like 16kHz or 32kz just by changing the clock source in TCCR1B
hey Circuitsville,
it took me a while to understand timers but then, it is a peace of cake to generate any PWM frequency from a few Hz up to hundreds of KHz or even more.
Here is another example showing the basic timer programmation (from post #5 to the end of thread):
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1252073278
please note you can have different ways to generate same frequency by playing with clock scaling, using a 8bit or 16bit Atmega timer along with TOP value but each way might have not same PW resolution.
Hi guys. I did some testing on 0017.
I modified turnOffPWM in wiring_digital.c, and profiled various configurations of inline/noninline, switch, if, and else if for the timer selection.
Here's the code that I tested with:
int unConstPwmPin = 3;
int unConstPin = 2;
const int constPwmPin = 5;
const int constPin = 12;
int index;
long time;
void setup() {
// set the digital pins as output:
pinMode(unConstPwmPin, OUTPUT);
pinMode(constPwmPin, OUTPUT);
pinMode(unConstPin, OUTPUT);
pinMode(constPin, OUTPUT);
Serial.begin(9600);
}
void loop()
{
int var = LOW;
time = micros();
for (index = 0; index < 10000; index++)
{
digitalWrite(unConstPwmPin, HIGH);
digitalWrite(unConstPwmPin, LOW);
digitalWrite(constPwmPin, HIGH);
digitalWrite(constPwmPin, LOW);
digitalWrite(unConstPin, HIGH);
digitalWrite(unConstPin, LOW);
digitalWrite(constPin, HIGH);
digitalWrite(constPin, LOW);
digitalWrite(unConstPwmPin, var);
digitalWrite(unConstPwmPin, var);
digitalWrite(constPwmPin, var);
digitalWrite(constPwmPin, var);
digitalWrite(unConstPin, var);
digitalWrite(unConstPin, var);
digitalWrite(constPin, var);
digitalWrite(constPin, var);
var = !var;
digitalWrite(unConstPwmPin, var);
digitalWrite(unConstPwmPin, var);
digitalWrite(constPwmPin, var);
digitalWrite(constPwmPin, var);
digitalWrite(unConstPin, var);
digitalWrite(unConstPin, var);
digitalWrite(constPin, var);
digitalWrite(constPin, var);
}
time = micros() - time;
Serial.println(time);
delay(1000);
}
And here are the results:
Noninline switch = 1004456
Inline switch = 1004452
Noninline if=1019544
Inline if=1019544
Noninline elseif = 1019544
Inline elseif = 1019544
For the inline switch, this works out to be approximately 4.1852166666666666666666666666667 (etc) microseconds per pin. Note that I'm treating PWM and non-PWM pins the same, to find the AVERAGE efficiency. This works out to be approximately 239kHz.
If I tried only constant non-PWM pins with consant inputs, the frequency is about 270 kHz, whereas plain if's is 274kHz. For non-constant non-PWM pins with non-constant inputs, switch gives 266kHz; if gives 271kHz.
For a constant PWM pin with constant inputs, using switch, the frequency is 218kHz; using if's, it's exactly the same. For non-constant pins with non-constant inputs, switch gives 215 kHz; for if's, 199kHz.
You should add "static" to the const variables. The compiler will not truly treat them as compile time constants unless they are static, because even though they are const, they are visible to other compile units that could discard the const qualifier. That forces the compiler to allocate them like any other variable. Only with "static const" is it truly a constant.
Today that probably won't make any difference. But when (if ever?) my digitalWrite optimization gets included in Arduino, it will make a HUGE difference. That code is in issue #140.
http://code.google.com/p/arduino/issues/detail?id=140
Also, I ran this code on a Teensy (which also does not have that optimization as of teensyduino 0.8, but does have other optimizations I wrote earlier), and I get 584128. That code is open source and you can get if from my website, if you're interested. Just run the installer and look for it in the hardware directory.
I'm also working on some assembly optimizations that will further speed up the non-const cases.
I don't understand
and I get 584128.
, what does it mean 584218 ?
Today that probably won't make any difference. But when (if ever?) my digitalWrite optimization gets included in Arduino, it will make a HUGE difference. That code is in issue #140.
Google Code Archive - Long-term storage for Google Code Project Hosting.
That code doesn't work for me. What is _digitalWrite?
_digitalWrite would be the current slow function.
If modify the macro as follows you can run the code by calling fastWrite in your sketch.
if the pin and value are both constants, a single op code is used, if pin or port are variables then the exisitng slow digitalWrite is called.
#define fastWrite(P, V) \
if (__builtin_constant_p(P) && __builtin_constant_p(V)) { \
if (digitalPinToTimer(P)) \
bitClear(*digitalPinToTimer(P), digitalPinToTimerBit(P)); \
bitWrite(*digitalPinToPortReg(P), digitalPinToBit(P), (V)); \
} else { \
digitalWrite((P), (V)); \
}
I think paul's macro assumed that the implimentation of the current digitalWrite would be renamed to _digitalWrite
@selfonlypath: that number is TraumaPony's benchmark. Smaller numbers are better, meaning digitalWrite is running faster.
The number is the elapsed microseconds to perform several different digitalWrites 10000 times. Just copy-n-paste TraumaPony's sketch and run it on your board, and you'll see a number in the Serial Monitor. If you have LEDs connected to those pins, they will blink. If you're using a board with different pinout from the '168 or '328 based Arduino, edit the pin numbers so the two pwm pins are ones with PWM and others aren't.
Also, it looks like I was incorrect about needing "static". In this case, the complier does seem to be able to treat those numbers as compile time constants. I have seen it fail to do so in other cases, and honestly I do not fully understand why it would be different. I tried both ways and even read through disassembly of the compiler generated code, and static does not make any difference in this case.